简体   繁体   English

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

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

I've just updated my MVC4 app to MVC5 and for some reason this appears to have completely broken my MEF implementation at the same time. 我刚刚将我的MVC4应用程序更新为MVC5,由于某种原因,这似乎完全破坏了我的MEF实现。

The code snippets below from my solutions have been running without a hitch for over a year and I'm not entire clear on what the solution is. 我的解决方案中的以下代码片段已经运行了一年多,而我还不清楚该解决方案是什么。

I have two solutions, an MVC5 web site and a MVC WebAPI 2 solution. 我有两个解决方案,一个MVC5网站和一个MVC WebAPI 2解决方案。

The error I'm seeing one the web site is: 我在网站上看到的错误是:

"Currently composing another batch in this ComposablePartExportProvider. Only one batch can be composed at a time."

And on the WebAPI solution none of the [Import] marked fields in the controller classes are populated and generate "Object not set to an instance of an object". 在WebAPI解决方案上,不会填充控制器类中的[Import]标记字段,也不会生成“ Object not set to a object instance”。 All very confusing considering the same code has been running for over a year with no problems. 考虑到相同的代码,所有令人困惑的问题已经运行了一年多,没有任何问题。

From checking the container parts all the expected and required parts are present. 通过检查容器零件,可以看到所有期望的零件和必需的零件。

MVC5 Web Site Mef Config 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 Config 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 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;
    }
}

All the controllers in both solutions are marked like this: 两种解决方案中的所有控制器均标记为:

[Export(typeof(MyController)), PartCreationPolicy(CreationPolicy.NonShared)]

What I'm finding really confusing is that this same code has been running witout problems for a long time and since I haven't changed the .NET version (4.5) this should be running the same MEF code. 我发现真正令人困惑的是,相同的代码已经运行了很长时间了,并且由于我没有更改.NET版本(4.5),所以它应该运行相同的MEF代码。

There is obviously a problem with what I'm doing and I've read that changing from using the ComposeParts method to using the SatisfyImportsOnce method fixes the issue. 我在做什么显然存在问题,并且我读到从使用ComposeParts方法更改为使用SatisfyImportsOnce方法可以解决此问题。 When I changed the code to use this method I no longer get the batch composing error but my [Import] properties are still null on the API controllers despite the parts being in the container. 当我更改代码以使用此方法时,我不再遇到batch composing错误,但是尽管部分在容器中,但API控制器上的[Import]属性仍然为空。

I'm really not clear on why this has started happening in the first place after upgrading the the newer version of MVC and WebAPI and I'm unclear on what the final solution is. 我真的不清楚为什么在升级较新版本的MVC和WebAPI之后首先开始发生这种情况,也不清楚最终的解决方案是什么。

My implementation is largely based on this: 我的实现主要基于此:

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

Has anyone seen similar and fixed this? 有没有人看过类似的东西并解决了这个问题? What was the fix in your situation? 您的情况如何解决?

I had the same problem, I was able to import dll in a "extensions" folder where I was building the plug-in projects, my web-api was a simple get to import angularjs routing so the angularjs controllers in the dll work but I tried all tutorial on how to import ApiControllers defined in the dll with MEF and nothing works for some obscur reasons. 我遇到了同样的问题,我能够在构建插件项目的“扩展”文件夹中导入dll,我的web-api是导入angularjs路由的简单方法,因此dll中的angularjs控制器可以工作,但我尝试了所有有关如何使用MEF导入dll中定义的ApiControllers的教程,但由于某些晦涩的原因而没有任何效果。 I don't know if it would be a viable solution for you but moving the dll from that "extensions" folder to the bin folder of the main project made the ApiControllers discovered automaticaly and everything works like a charm I don't need to import the controllers with MEF (I still import the .js and.html with MEF but thats all), looks like MVC implemented its own way to discover controllers in the running environnement. 我不知道这是否对您来说是一个可行的解决方案,但是将dll从该“扩展名”文件夹移至主项目的bin文件夹后,ApiControllers会自动被发现,并且一切正常,就像我不需要导入的超级按钮一样使用MEF的控制器(我仍然使用MEF导入.js和.html,仅此而已),看起来MVC实现了自己的方式来发现正在运行的环境中的控制器。

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

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