返回实现通用接口的类的类型
问题描述:
SomeRepository
类型不会被GetPublicClassesFromApplicationAssembly
返回。我想要返回所有扩展IRepository的类。任何人都可以看到问题吗?返回实现通用接口的类的类型
private Type[] GetPublicClassesFromApplicationAssembly()
{
return typeof (SomeRepository).Assembly.GetExportedTypes()
.Where(t => t.IsClass)
.Where(t => t.IsAbstract == false)
.Where(r => r.IsAssignableFrom(typeof(IRepository<>)))
.OrderBy(t => t.Name)
.ToArray();
}
public class SomeRepository : IRepository<SomeDomainClass> {}
public interface IRepository<T> where T : PrimaryKeyBase {}
public class SomeDomainClass: PrimaryKeyBase {}
答
SomeRepository
不可分配从IRepository<>
,这不是一个 “真正的” 类型;它可以从IRepository<SomeDomainClass>
分配。您需要使用GetInterface
而不是IsAssignableFrom
:
.Where(r => r.GetInterface("IRepository`1") != null
答
如果它有用,这里是一个例行我写了同样的目的:
使用方法如下
.Where(r => r.IsDerivedFrom(typeof(IRepository<>)))
这里,它是
public static bool IsDerivedFrom(this Type type, Type inter)
{
if (type.IsSubclassOf(inter))
return true;
if (IsDerivedFromImp(type, inter))
return true;
foreach (var i in type.GetInterfaces())
{
if (IsDerivedFromImp(i, inter))
return true;
}
return false;
}
/// <summary>
/// type A is equivalent to B if
/// 1. They are they same type, AND
/// 2. Their generic arguments match
/// </summary>
/// <param name="iLhs"></param>
/// <param name="iRhs"></param>
/// <returns></returns>
private static bool IsDerivedFromImp(Type iLhs, Type iRhs)
{
if (iLhs == iRhs)
{
return true;
}
if (iLhs.IsGenericType && iRhs.IsGenericType)
{
iRhs.GetGenericArguments();
if (iLhs.GetGenericTypeDefinition() != iRhs.GetGenericTypeDefinition())
{
return false;
}
// Generic arguments must be match
var lhsArgs = iLhs.GetGenericArguments();
var rhsArgs = iRhs.GetGenericArguments();
for (int x = 0; x < rhsArgs.Length; x++)
{
// ie IList<> is derived from IList<>, is true
if (lhsArgs[x].IsGenericParameter && rhsArgs[x].IsGenericParameter)
{
continue;
}
// ie IList<string> is derived from IList<>, is true
if (!lhsArgs[x].IsGenericParameter && rhsArgs[x].IsGenericParameter)
{
continue;
}
// ie IList<> is derived from IList<string>, is false
if (lhsArgs[x].IsGenericParameter && !rhsArgs[x].IsGenericParameter)
{
return false;
}
// ie IDo<string> is derived from IDo<int>, is false
if (lhsArgs[x] != rhsArgs[x])
{
return false;
}
}
return true;
}
return false;
}