繁体   English   中英

将MVC4和WebAPI更新为MVC5和WebAPI 2损坏的MEF实施

[英]Updating MVC4 & WebAPI to MVC5 & WebAPI 2 Broken MEF Implementation

我刚刚将我的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 a object 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错误,但是尽管部分在容器中,但API控制器上的[Import]属性仍然为空。

我真的不清楚为什么在升级较新版本的MVC和WebAPI之后首先开始发生这种情况,也不清楚最终的解决方案是什么。

我的实现主要基于此:

http://kennytordeur.blogspot.co.uk/2012/08/mef-in-aspnet-mvc-4-and-webapi.html

有没有人看过类似的东西并解决了这个问题? 您的情况如何解决?

我遇到了同样的问题,我能够在构建插件项目的“扩展”文件夹中导入dll,我的web-api是导入angularjs路由的简单方法,因此dll中的angularjs控制器可以工作,但我尝试了所有有关如何使用MEF导入dll中定义的ApiControllers的教程,但由于某些晦涩的原因而没有任何效果。 我不知道这是否对您来说是一个可行的解决方案,但是将dll从该“扩展名”文件夹移至主项目的bin文件夹后,ApiControllers会自动被发现,并且一切正常,就像我不需要导入的超级按钮一样使用MEF的控制器(我仍然使用MEF导入.js和.html,仅此而已),看起来MVC实现了自己的方式来发现正在运行的环境中的控制器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM