我试图让一些插件的东西在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属性,却被忽略了?
最佳答案
您的代码对我有用;我在一个空的WinForms应用程序外壳中尝试过的代码如下。
如果我不得不猜测您的问题,我相信这与以下任何一项有关:
FirstOrDefault:您查看的程序集是否有两个实现IModule的类,而发现的第一个不是SomeModule而是其他东西?这是您的代码永远找不到SomeModule的一种方式。
在GetModuleEntry中对IModule的引用:在定义GetModuleEntry的项目中,是否可能要引用包含IModule接口的程序集的较新版本或不同版本?除非GetModuleEntry方法引用的是包含SomeModule的程序集引用的IModule定义的确切DLL,否则您可能会遇到问题。
我认为后者很有可能,或者至少会为您指出解决问题的正确方向。
这是可以正常工作的测试代码,因为只有一个类实现IMyInterface(因此FirstOrDefault是OK),并且所有类/接口都在同一模块中:
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!");
}
}
}