assembly.GetTypes()和GetExportedTypes()不返回所有公共对象

时间:2014-08-07 15:45:35

标签: c# reflection system.reflection

我正在尝试在asp.net mvc中使用一些插件。我的插件DLL有一个控制器以及一个描述符/模块类。

控制器签名如下所示:

[Export("SomeController", typeof(System.Web.Mvc.IController))]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
public class SomeController : System.Web.Mvc.Controller
{ }

并且模块描述符类具有以下签名:

[Export("SomeModule", typeof(Plugins.IModule))]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
public class SomeModule : Plugins.IModule
{ }

现在这个“插件”程序集动态加载没有问题。当我使用GetTypes()和GetExportedTypes()方法时出现问题:

private void GetModuleEntry(Assembly a) {
   IModule module = null;
   Type type = a.GetTypes()
                .Where(t => t.GetInterface(typeof(IModule).Name) != null).FirstOrDefault();
   if (type != null) { do something }
   else { throw exception; }
}

因此,问题在于给定上面的类签名,GetTypes()和GetExportedTypes()(不使用Where子句)都只返回SomeController类。 SomeModule类永远不会被任何一种方法列出!我检查了我的设置断点并在执行带有Where子句的下一个语句之前在立即命令窗口上调用GetTypes()和GetExportedTypes()。

那为什么呢?为什么我的模块类被省略了,即使它是PUBLIC类并且还有Exported属性?

1 个答案:

答案 0 :(得分:0)

您的代码适合我;我在一个空的WinForms应用程序shell中尝试的代码如下所示。

如果我不得不猜测你的问题,我认为它与其中任何一个有关:

FirstOrDefault :你看到里面的程序集是否有可能有两个实现IModule的类,找到的第一个类不是 SomeModule 但有些不同?这是您的代码永远找不到的一种方式 SomeModule

GetModuleEntry中对IModule的引用:在您定义GetModuleEntry的项目中,您是否可能引用包含IModule接口的程序集的较新版本或不同版本?除非GetModuleEntry方法引用包含由包含SomeModule的程序集引用的IModule定义的确切DLL,否则可能会遇到问题。

我认为后者最有可能,或者至少会指出你正确的方向来解决问题。

这是可以正常工作的测试代码,因为只有一个实现IMyInterface的类(所以FirstOrDefault没问题),并且所有类/接口都在同一个模块中:

public interface IMyInterface
{ }

public class bar
{ }

[Export("SomeController", typeof(bar))]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
public class foo : bar
{ }

[Export("SomeModule", typeof(IMyInterface))]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
public class ifoo : IMyInterface
{ }

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        Assembly a = System.Reflection.Assembly.GetExecutingAssembly();

        Type type = a.GetTypes()
            .Where(t => t.GetInterface(typeof(IMyInterface).Name) != null).FirstOrDefault();

        if (type != null) // type is of Type ifoo
        {
            Console.WriteLine("Success!"); 
        }

    }
}