IsAssignableFrom()在返回true时返回false

我正在开发一个插件系统,它可以加载包含在指定文件夹中的.dll。 然后我使用reflection来加载程序集,遍历它们包含的类型并识别任何实现我的IPlugin接口的程序。

我正在检查这个代码类似于以下代码:

 foreach(Type t in myTypes ) { if( typeof(IPlugin).IsAssignableFrom(t) ) { ... } } 

出于某种原因,IsAssignableFrom()在返回true时保持返回false。 我已经尝试通过显式赋予它一个应该传递的类型替换t ,并且它工作正常,但由于某种原因它不能处理从加载的程序集返回的类型。 为了让事情变得陌生,代码在我的同事的机器上工作正常,但在我的机器上却没有。

有谁知道任何可能导致这种行为的事情?

谢谢

当包含当前程序集引用的类型IPlugin的程序集与包含您正在迭代的类型的程序集引用的程序集不匹配时,通常会发生这种情况。

我建议你打印:

 typeof (IPlugin).Module.FullyQualifiedName 

 foreach (var type in t.GetInterfaces ()) { Console.WriteLine (type.Module.FullyQualifiedName) } 

要查看不匹配的位置。

其他一些答案提到了IsAssignableFrom方法名称缺乏明确性。 我同意,结果是以错误的方式使用它。

尝试在代码中反转对象 ,然后查看它是否有效。 例如:

更换:

 if (typeof(IPlugin).IsAssignableFrom(t)) 

有:

 if (t.IsAssignableFrom(typeof(IPlugin))) 

通过这样做,我不仅让它工作,而且开始了解这种方法实际上做了什么。

当接口在单独的程序集中定义为实现类型时,我遇到了同样的问题。 从根文件夹中迭代和加载程序集,其中包含带有类和带接口的dll的dll导致类型不匹配,如上所述。

一种解决方案是将LoadFrom()更改为LoadFile() LoadFrom方法有一些缺点,这是其中之一:

如果已加载具有相同标识的程序集,则即使指定了不同的路径,LoadFrom也会返回已加载的程序集。

解决此问题的另一种方法是将具有实现接口的类型的所有dll放入单独的文件夹中,而不是复制引用的程序集( CopyLocal = False ),这样Assembly.LoadFrom将不会在内存中加载包含接口的dll。

我在Java中工作,它具有相同的API方法,在阅读代码时我无法理解它(出于某种原因); 因此,我总是反过来看,因为在你的情况下,“t可以分配给IPlugin。”所以,如果C#有“是”,如Jonathon建议的那样,我会一直使用它 – 当在Java中反映“instanceof”不起作用时类对象,仅对象的实例。

有时这是动态程序集引用另一个程序集的问题。

一个简单的做法是禁用程序集上的本地副本(在visual studio中右键单击引用并将copy local设置为false)。 这样可以更容易确定程序集所在的目录。

您还可以实现一个程序集解析器,以防.NET不知道如何初始化该类型。

  AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler([Resolve Function]); 

应用于测试inheritance或检测接口实现时,Type.IsAssignableFrom方法的名称含糊不清且令人困惑。 以下用于这些目的的包装器会更有意义:

  public static bool CanBeTreatedAsType(this Type CurrentType, Type TypeToCompareWith) { // Always return false if either Type is null if (CurrentType == null || TypeToCompareWith == null) return false; // Return the result of the assignability test return TypeToCompareWith.IsAssignableFrom(CurrentType); } 

然后,可以有更易理解的应用程序代码,例如:

  bool CanBeTreatedAs = typeof(SimpleChildClass).CanBeTreatedAsType(typeof(SimpleClass)); CanBeTreatedAs = typeof(SimpleClass).CanBeTreatedAsType(typeof(IDisposable)); 

此方法代替’is’关键字的优点是它可以在运行时用于测试未知的任意类型,而’is’关键字(和通用的Type参数)需要特定类型的编译时知识。