C# DefinedTypes正在返回系统运行时类型
看到这个截图了吗 它显示所有定义的类型都是C# DefinedTypes正在返回系统运行时类型,c#,C#,看到这个截图了吗 它显示所有定义的类型都是RuntimeType,然后我使用myType.IsAssignableFrom(definedType),它永远不会返回true 这是可以理解的,因为它是RuntimeType,但是如何从中获取实际的类型呢 public static List<T> GetAllDerivedTypes<T>(this Assembly assembly) { var type = typeof(T); var isInter
RuntimeType
,然后我使用myType.IsAssignableFrom(definedType)
,它永远不会返回true
这是可以理解的,因为它是RuntimeType
,但是如何从中获取实际的类型呢
public static List<T> GetAllDerivedTypes<T>(this Assembly assembly)
{
var type = typeof(T);
var isInterface = type.IsInterface;
var name = type.Name;
if (!isInterface)
{
throw new Exception("Not an interface type");
}
List<object> types = new List<object>();
foreach (var definedType in assembly.DefinedTypes)
{
var isAssignableFrom = definedType.IsAssignableFrom(type);
var interfaces = definedType.ImplementedInterfaces.Where(x => x.Name == name);
if (isAssignableFrom)
{
types.Add(definedType);
}
}
return types.Cast<T>().ToList();
}
公共静态列表GetAllDerivedTypes(此程序集)
{
var类型=类型(T);
var isInterface=type.isInterface;
var name=type.name;
如果(!i接口)
{
抛出新异常(“不是接口类型”);
}
列表类型=新列表();
foreach(程序集中的变量定义类型。定义类型)
{
var isAssignableFrom=definedType.isAssignableFrom(类型);
var interfaces=definedType.ImplementedInterfaces.Where(x=>x.Name==Name);
如果(isAssignableFrom)
{
类型。添加(定义类型);
}
}
返回类型.Cast().ToList();
}
我可以很容易地将它简化为一个
Linq
语句,但我已经将它放大了,这样我就可以看到哪里出了问题。它将永远不会返回T
的所有派生类型,其中T:interface
您得到的方法调用是错误的。阅读definedType.IsAssignableFrom(type)
将返回true,如果type是从definedType派生的,则返回true,反之亦然
从文档中:
public virtual bool IsAssignableFrom(Type c)
如果以下任一项为真,则将返回真:
- c和当前实例表示相同的类型
- c直接或间接地从当前实例派生
- 当前实例是c实现的接口
- c是泛型类型参数,当前实例表示c的一个约束
- c表示值类型,当前实例表示可为null(在visualbasic中是c的可为null)
var isAssignableFrom = type.IsAssignableFrom(definedType);
Chris已经回答了这样一个事实,即您正在以错误的顺序使用
IsAssignableFrom
。您需要调用typeof(T)。IsAssignableFrom(definedType)
以检查是否可以将definedType类型的对象分配给T类型的变量
但您的代码还有另一个问题,我将其简化为这一个问题,希望能够突出它:
public static List<T> GetAllDerivedTypes<T>(this Assembly assembly)
{
// …
List<object> types = new List<object>();
foreach (var definedType in assembly.DefinedTypes)
{
// …
types.Add(definedType);
}
return types.Cast<T>().ToList();
}
所以我做错了两件事
- 未正确使用
是可从中识别的
- 当它们是类型而不是实例化对象时使用
Cast
解决方案:
public static List<T> GetAllDerivedTypes<T>(this Assembly assembly)
{
var type = typeof(T);
var isInterface = type.IsInterface;
if (!isInterface)
{
throw new Exception("Not an interface type");
}
return assembly
.DefinedTypes
.Where(x => type.IsAssignableFrom(x) && !x.IsInterface)
.Select(Activator.CreateInstance)
.Cast<T>()
.ToList();
}
公共静态列表GetAllDerivedTypes(此程序集)
{
var类型=类型(T);
var isInterface=type.isInterface;
如果(!i接口)
{
抛出新异常(“不是接口类型”);
}
返回组件
.定义类型
.Where(x=>type.IsAssignableFrom(x)&&!x.IsInterface)
.Select(Activator.CreateInstance)
.Cast()
.ToList();
}
看起来您使用的IsAssignableFrom
方式不对。尝试type.IsAssignableFrom(definedType)
但即使在这之后,您的方法也无法工作,因为您试图通过调用types
上的cast
将TypeInfo
转换为t
。这是行不通的。谢谢@MarcinJuraszek确实是我的问题类型是一个接口,我想看看definedType是否从中派生出来,这就是你所说的吗?我知道列表是错误的,无法工作,我完全知道,我刚刚关闭了编译器。我只是想看看为什么派生类型不起作用t
是一个接口,所以这仍然适用于这个“所以这仍然适用于这个”-不,它不会吗?不管它是否是一个接口。我不知道你在说什么。但是无论如何,IsAssignable
现在对我来说很有用。我是说,t
是否是接口对代码来说并不重要。您找到的类型仍然是Type
对象,您无法将其强制转换为类型T
。顺便说一句,我希望你有更好的理由对这个答案投反对票,而不是因为我对你的反对票……对于没有公共默认构造函数(甚至是抽象类型)的类型,这肯定会失败。另外,当你没有新的答案可以添加到现有的答案中时,不要自我回答你的问题。你应该给出有用的答案,这很有帮助。另外,我知道这个接口的所有派生类型都有默认构造函数,或者应该有。所以对于我来说这是完美的。我会投票其他答案,但这是正确的解决方案。即使你知道你的类型有一个默认的构造函数,你仍然应该考虑添加一个附加的检查或者至少检查异常(例如,代码> MISSION MeOraceExptudio</代码>)。-确保您找到的所有类型都允许使用默认构造函数进行实例化。毕竟,您的接口无法实现这一点。
public static List<T> GetAllDerivedTypes<T>(this Assembly assembly)
{
var type = typeof(T);
var isInterface = type.IsInterface;
if (!isInterface)
{
throw new Exception("Not an interface type");
}
return assembly
.DefinedTypes
.Where(x => type.IsAssignableFrom(x) && !x.IsInterface)
.Select(Activator.CreateInstance)
.Cast<T>()
.ToList();
}