2013-12-23 38 views
0

我有一個要求,我必須在我的應用程序中支持兩種類型的容器。因此,我已經創建了一個提供2種類型的容器,即從galasoft與MEF和IOC容器定製服務定位器

  1. SimpleIoc(Galasoft)的自定義服務定位

  2. MefServiceLocatorAdapter

所以我創建了一個共同的服務定位器類即

public class CommonServiceLocator : ServiceLocatorImplBase 
{ 
    private IServiceLocator _iocContainer, _mefContainer; 

    public CommonServiceLocator(IServiceLocator iocLocator, IServiceLocator mefLocator) 
    { 
     _iocContainer = iocLocator; 
     _mefContainer = mefLocator; 
    } 

    protected override IEnumerable<object> DoGetAllInstances(Type serviceType) 
    { 

     IEnumerable<object> services; 
     try 
     { 
      services = _iocContainer.GetAllInstances(serviceType); 
     } 
     catch (Exception) 
     { 
      //Current assumption is that if IocContainer doesn't contain an instance then 
      //it should look for MefContainer for values 
      services = _mefContainer.GetAllInstances(serviceType); 
     } 
     return services; 
    } 

    protected override object DoGetInstance(Type serviceType, string key) 
    { 
     object service; 
     try 
     { 
      service = _iocContainer.GetInstance(serviceType, key); 
     } 
     catch (Exception) 
     { 
      //Current assumption is that if IocContainer doesn't contain an instance then 
      //it should look for MefContainer for values 
      service = _mefContainer.GetInstance(serviceType, key); //<== This fails to get an instance 
     } 
     return service; 
    } 

    public override object GetInstance(Type serviceType, string key) 
    { 
     return DoGetInstance(serviceType, key); 
    } 

    public override object GetInstance(Type serviceType) 
    { 
     return GetInstance(serviceType, null); 
    } 
} 

現在,問題是當我嘗試通過IOC容器使用GetInstance()方法獲得類實例時它工作正常。但是,通過MefContainer獲取類實例會引發一些錯誤(「System.Core.dll中發生類型'System.InvalidOperationException'的第一次機會異常)。我創建了一個測試課來測試這種情況:

public class ServiceLocatorTest 
{ 
    public void CommonServiceLocatorInstanceTest() 
    { 
     var serviceLocator = new SimpleIoc(); 
     serviceLocator.Register<GalaSoftIocData>(); 

     AggregateCatalog catalog = new AggregateCatalog(); 
     catalog.Catalogs.Add(new AssemblyCatalog(typeof(MefCompositionAddin).Assembly)); 
     CompositionContainer compContainer = new CompositionContainer(catalog); 

     CompositionBatch batch = new CompositionBatch(); 

     batch.AddPart(AttributedModelServices.CreatePart(new MefCompositionAddin())); 

     compContainer.Compose(batch); 

     var vl = compContainer.GetExportedValue<MefCompositionAddin>(); // <== This gives instance correctly 
     var mefserviceLocator = new MefServiceLocatorAdapter(compContainer); 
     var commonServiceLocator = new CommonServiceLocator(serviceLocator, mefserviceLocator); 
     var galaSoftData = commonServiceLocator.GetInstance(typeof(GalaSoftIocData)); 
     var mefData = commonServiceLocator.GetInstance(typeof(MefCompositionAddin)); 
    } 
} 

[Export] 
class MefCompositionAddin 
{ 

    public string MyData { get { return "Mef's Data composed"; } } 

    [Import] 
    public MefCompositionAddin MyObj { get; set; } 
} 

class MefCompositionData 
{ 
    [Import] 
    public MefCompositionAddin MyAddin { get; set; } 
} 

class GalaSoftIocData 
{ 
    public string MyData { get { return "Galasoft's Data composed"; } } 
} 

請讓我知道我是否錯過了任何東西。以及可能的原因是什麼。感謝大家提前給予的幫助。

+0

你能否提供關於這個異常的更多細節,例如:堆棧跟蹤(如果它很長,幾個頂級調用應該足夠)?它是否有內部異常?發生 –

+0

System.InvalidOperationException 的HResult = -2146233079 消息=序列包含一個以上的元件 源= System.Core程序 堆棧跟蹤:在System.Linq.Enumerable.Single [TSource](IEnumerable'1源) 在微軟。 Practices.Prism.MefExtensions.MefServiceLocatorAdapter.DoGetInstance(Type serviceType,String key) at c:\ Home \ Chris \ Projects \ CommonServiceLocator \ main \ Microsoft中的Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(類型serviceType,String key)。 Practices.ServiceLocation \ ServiceLocatorImplBase.cs:line 49 InnerException: – nishantcop

+0

此外,沒有InnerException – nishantcop

回答

2

我相信您正在使用Prism庫中提供的MefServiceLocatorAdapter。這是它的DoGetInstance方法的代碼:

protected override object DoGetInstance(Type serviceType, string key) 
{ 
    IEnumerable<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, key); 
    if ((exports != null) && (exports.Count() > 0)) 
    { 
     // If there is more than one value, this will throw an InvalidOperationException, 
     // which will be wrapped by the base class as an ActivationException. 
     return exports.Single().Value; 
    } 

    throw new ActivationException(
     this.FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key)); 
} 

正如你可以在註釋中看到的,如果你有不止一種類型的出口到相應服務類型和密鑰它會拋出你所描述,由於異常到單一方法。

您可以檢查您的導出應用程序,看看是否有某種類型映射到多個類(或多次導出相同的類)或重寫該方法,以便它不引發異常(例如使用FirstOrDefault代替

注:我沒有添加上述評論,它包含在庫的代碼。

+0

確實這是真正的原因。我注意到下面的額外行創建了一些額外的實例: AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(typeof(MefCompositionAddin).Assembly)); – nishantcop