2014-06-20 75 views
1

我剛剛將MVC4應用程序更新爲MVC5,出於某種原因,這似乎已經完全破壞了我的MEF實現。將MVC4和WebAPI更新爲MVC5和WebAPI 2破解MEF實現

從我的解決方案下面的代碼片段已經運行了一年多,並且我不完全清楚解決方案是什麼。

我有兩個解決方案,一個MVC5網站和一個MVC WebAPI 2解決方案。

我看到一個網站上的錯誤是:

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

而且對解決方案的WebAPI沒有[導入]的標記在控制器類字段將被填充,併產生「對象未設置爲一個對象的實例「。考慮到相同的代碼已經運行了一年多,沒有任何問題,所有這些都非常混亂。

從檢查容器部件中可以看到所有預期的和必需的部件。

MVC5網站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(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方法修復問題。當我更改代碼以使用此方法時,儘管部件位於容器中,但我不再在API控制器上獲得batch composing錯誤,但我的[Import]屬性仍爲空。

我真的不清楚爲什麼在升級更新版本的MVC和WebAPI後,爲什麼這開始發生,我不清楚最終解決方案是什麼。

我的實現在很大程度上是基於這樣的:

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

有沒有人見過類似的固定呢?你的情況有什麼修復?

+0

自從問這個問題以來,我已經嘗試了各種解決方案,並且它徹底壞了。看起來WebAPI2在這方面的工作有很大的不同,任何人得到這個信息都會有幫助。 – Jammer

回答

0

我有同樣的問題,我能夠在我正在構建插件項目的「extensions」文件夾中導入dll,我的web-api是一個簡單的獲取導入angularjs路由,所以angularjs控制器在DLL工作,但我嘗試了所有關於如何導入在MEF中定義的ApiController的教程和沒有任何工作原因的一些obscur。我不知道這是否是一個可行的解決方案,但將dll從該「extensions」文件夾移動到主項目的bin文件夾中,使得ApiControllers發現automaticaly並且一切都像魅力一樣工作,我不需要導入帶MEF的控制器(我仍然使用MEF導入.js和.html,但都是這樣),看起來MVC實現了自己的方式來發現運行環境中的控制器。

+0

似乎很奇怪不是。感覺像一個黑色的藝術。 – Jammer

+0

看起來我今天要再次嘗試這次升級。祝我好運!哈! – Jammer