你的技术非常可靠,即使在部分信任的情况下也能发挥作用。这书呆子晚餐MEF http://www.hanselman.com/blog/ExtendingNerdDinnerAddingMEFAndPluginsToASPNETMVC.aspx示例的扩展允许您按照约定处理发现控制器并自动将它们放入 MEF 导出中,而无需使用 MEF 属性标记它们。但是直接管理零件目录在部分信任中不起作用,因此书呆子晚餐 MEF 技术在部分信任中不起作用。
如果您完全信任地工作,并且希望控制器进行基于约定的发现,请从 Nerddinner MEF 示例开始,但您可能还应该阅读 nerddinner MEF 示例的几个主要问题,如果您自己的应用程序模型会出现这些问题是一个单独的类库项目。我关于这些案例的博客 http://reddnet.net/post/2010/06/22/Hooked-on-MEF-Using-MEF-in-ASPNET-MVC-and-the-Nerd-Dinner-MEF-sample-fix.aspx并提出了一些修复建议。
如果您对基于惯例的发现内容不太感兴趣,那么书呆子晚餐样本就有点过度设计了。您的解决方案可能就这样......并且也可以在部分信任的情况下工作,这始终是一个好处。
[update]我确实发现了你的技术的一个潜在问题:
var controllerExport = controllers.Where(x => x.Value.GetType() ==
controllerType).FirstOrDefault();
在此处的 where 子句中,您在部件集合中的每个导出上调用 .Value...这实际上会导致每个导出被组合并实例化以便进行评估。这可能是一个令人讨厌的性能问题。
您可以考虑使用命名导出合约来装饰您的控制器,如下所示:
[Export("Home", typeof(IController))]
然后使用像这样的控制器工厂:
public class MefControllerFactory: IControllerFactory
{
private CompositionContainer _Container;
public MefControllerFactory(Assembly assembly)
{
_Container = new CompositionContainer(new AssemblyCatalog(assembly));
}
#region IControllerFactory Members
public IController CreateController(RequestContext requestContext, string controllerName)
{
var controller = _Container.GetExportedValue<IController>(controllerName);
if (controller == null)
{
throw new HttpException(404, "Not found");
}
return controller;
}
public void ReleaseController(IController controller)
{
// nothing to do
}
#endregion
}