更新MVC4& WebAPI到MVC5& WebAPI 2破坏MEF实施

时间:2014-06-20 09:36:41

标签: c# asp.net-mvc asp.net-web-api mef

我刚刚将我的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

有没有人见过类似的并修好了这个?你情况有什么问题?

1 个答案:

答案 0 :(得分:0)

我有同样的问题,我能够在我正在构建插件项目的“extensions”文件夹中导入dll,我的web-api是一个简单的导入angularjs路由,所以在dll中的angularjs控制器工作,但我尝试了所有关于如何导入在MEF中使用MEF定义的ApiControllers的教程,并且没有任何因为某些阻碍原因而起作用。我不知道它是否是一个可行的解决方案,但将dll从“extensions”文件夹移动到主项目的bin文件夹,使ApiControllers自动发现,一切都像我不需要导入的魅力带有MEF的控制器(我仍然使用MEF导入.js和logo,但就是全部),看起来像MVC实现了自己的方式来发现运行环境中的控制器。