我有一个要求,我要在我的应用程序中支持两种类型的容器。因此,我创建了一个定制的ServiceLocator,它提供两种类型的容器,即
SimpleIoc(Galasoft)
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);
}
}
现在,问题是当我尝试使用GetInstance()方法通过IOC容器获取类实例时,它可以正常工作。但是,通过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 :(得分: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 代替单个。)
注意:我没有添加上述注释,它包含在库的代码中。