我刚刚将我的MVC4应用程序更新为MVC5,由于某种原因,这似乎完全破坏了我的MEF实现。
我的解决方案下面的代码片段已经运行了一年多,而且我不清楚解决方案是什么。
我有两个解决方案,一个MVC5网站和一个MVC WebAPI 2解决方案。
我看到网站的错误是:
"Currently composing another batch in this ComposablePartExportProvider. Only one batch can be composed at a time."
在WebAPI解决方案中,不会填充控制器类中的[Import]标记字段,并生成“Object not set to object of instance”。考虑到相同的代码,所有这些都非常令人困惑,已经运行了一年多没有问题。
从检查容器零件开始,所有预期和所需零件都存在。
MVC5网站Mef Config
public static class MefConfig
{
public static void RegisterMef()
{
var container = ConfigureContainer();
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
GlobalConfiguration.Configuration.DependencyResolver = new MefControllerFactory(container);
}
private static CompositionContainer ConfigureContainer()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(MoodConfig.AppBaseDirectory, @"bin\plugins")));
var container = new CompositionContainer(catalog, true);
return container;
}
WebApi 2 Mef配置
public static class MefConfig
{
public static void RegisterMef()
{
var container = ConfigureContainer();
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
GlobalConfiguration.Configuration.DependencyResolver = new MefControllerFactory(container);
}
private static CompositionContainer ConfigureContainer()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(ConfigHelper.AppBaseDirectory, @"bin\plugins")));
var container = new CompositionContainer(catalog, true);
return container;
}
}
MefControllerFactory
public class MefControllerFactory : DefaultControllerFactory, System.Web.Http.Dependencies.IDependencyResolver
{
private readonly CompositionContainer _compositionContainer;
private bool _disposed;
public MefControllerFactory(CompositionContainer compositionContainer)
{
_compositionContainer = compositionContainer;
}
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
var export = _compositionContainer.GetExports(serviceType, null, string.Empty).SingleOrDefault();
return null != export ? export.Value : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
var exports = _compositionContainer.GetExports(serviceType, null, string.Empty);
return exports.Select(export => export.Value).ToList();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
var baseMessage = "Not Found, controllerType is null";
if (requestContext != null)
{
throw new HttpException(404, string.Format("{0} RequestedUrl: {1}", baseMessage, requestContext.HttpContext.Request.Url));
}
throw new HttpException(404, baseMessage);
}
var export = _compositionContainer.GetExports(controllerType, null, string.Empty).SingleOrDefault();
IController result;
if (null != export)
{
result = export.Value as IController;
}
else
{
result = base.GetControllerInstance(requestContext, controllerType);
_compositionContainer.ComposeParts(result);
}
return result;
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Dispose managed resources.
}
}
_disposed = true;
}
}
两个解决方案中的所有控制器都标记为:
[Export(typeof(MyController)), PartCreationPolicy(CreationPolicy.NonShared)]
我发现真正令人困惑的是,这段相同的代码已经运行了很长时间的问题,而且由于我没有更改.NET版本(4.5),因此应该运行相同的MEF代码。
我正在做的事情显然存在问题,而且我已经读过,从使用ComposeParts方法改为使用SatisfyImportsOnce方法可以解决问题。当我更改代码以使用此方法时,我不再收到batch composing
错误,但我的[Import]
属性在API控制器上仍为空,尽管部件位于容器中。
在升级MVC和WebAPI的新版本之后,我真的不清楚为什么会在第一时间开始发生这种情况,我不清楚最终的解决方案是什么。
我的实施很大程度上基于此:
http://kennytordeur.blogspot.co.uk/2012/08/mef-in-aspnet-mvc-4-and-webapi.html
有没有人见过类似的并修好了这个?你情况有什么问题?
答案 0 :(得分:0)
我有同样的问题,我能够在我正在构建插件项目的“extensions”文件夹中导入dll,我的web-api是一个简单的导入angularjs路由,所以在dll中的angularjs控制器工作,但我尝试了所有关于如何导入在MEF中使用MEF定义的ApiControllers的教程,并且没有任何因为某些阻碍原因而起作用。我不知道它是否是一个可行的解决方案,但将dll从“extensions”文件夹移动到主项目的bin文件夹,使ApiControllers自动发现,一切都像我不需要导入的魅力带有MEF的控制器(我仍然使用MEF导入.js和logo,但就是全部),看起来像MVC实现了自己的方式来发现运行环境中的控制器。