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();
    }