DefinedTypes正在返回系统运行时类型

时间:2015-07-16 19:59:09

标签: c#

见此截图

 [img]

它显示所有定义的类型都是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();
}

我可以轻松地将其减少到一个Linq语句,但我已经把它搞砸了,所以我可以看到出了什么问题。它永远不会返回T的所有派生类型T : interface

3 个答案:

答案 0 :(得分:1)

您正在以错误的方式调用方法调用。阅读https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom(v=vs.110).aspx。如果type是从definedType派生的,那么definedType.IsAssignableFrom(type)将返回true,你希望反过来。

来自文档:

public virtual bool IsAssignableFrom(Type c)

如果满足以下任何条件,则返回true:

  • c,当前实例代表相同的类型。
  • c直接或间接地从当前实例派生。
  • 当前实例是c实现的接口。
  • c是泛型类型参数,当前实例表示c。
  • 的约束之一
  • c表示值类型,当前实例表示Nullable(在Visual Basic中为Nullable(Of C))。

所以请将您的电话改为:

var isAssignableFrom = type.IsAssignableFrom(definedType);

答案 1 :(得分:-1)

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();
}
每次迭代中的

definedTypeType,类型为Type的实例。因此,当您将其添加到types列表时,您要添加类型

然而,类型与具有泛型类型T(您的接口)类型的对象不同。因此types.Cast<T>()将失败,因为Type无法转换为您的接口类型T。同样,List<T>的返回值没有意义,因为您返回了 types 的列表,而不是具有接口类型的对象列表。

所以你想把它改成这个:

public static List<Type> GetAllDerivedTypes<T>(this Assembly assembly)
{
    // …
    List<Type> types = new List<Type>();
    foreach (var definedType in assembly.DefinedTypes)
    {
        // …
        types.Add(definedType);
    }

    return types;
}

答案 2 :(得分:-1)

所以我做错了两件事。

  • 未正确使用IsAssignableFrom
  • 当它们是类型而不是实例化对象时使用Cast<T>

解决方案:

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