Prism ServiceLocator的GetInstance和MEF

3

我正在尝试使用Microsoft.Practices.ServiceLocation.ServiceLocator和MEF。接口IServiceLocator定义了具有两个参数的GetInstance方法。第一个参数是serviceType,第二个参数是key。

[Export(typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class1 : IMyInterface 
{}

[Export(typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class2: IMyInterface 
{}

我想通过Prism ServiceLocator的GetInstance方法获取Class1的实例:
ServiceLocator.Current.GetInstance(typeof(IMyInterface),"Key");

但是我不知道“key”应该在哪里定义。我尝试在导出属性中定义key:
[Export("Key1",typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class1 : IMyInterface 
{}

[Export("Key2",typeof(IMyInterface)), PartCreationPolicy(CreationPolicy.Shared)]
public class Class2: IMyInterface 
{}

当我使用关键参数调用GetInstance方法时。
ServiceLocator.Current.GetInstance(typeof(IMyInterface),"Key1");

我遇到了Microsoft.Practices.ServiceLocation.ActivationException错误(尝试获取类型为IMyInterface,关键字为“Key1”的实例时发生激活错误)。请问有人知道如何定义导出关键字吗?

1个回答

6

Prism使用MefServiceLocatorAdapter来适配MEF的CompositionsContainerIServiceLocator接口。这是它用来获取您的部件的实际代码:

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));
}

正如你所看到的,你正确地导出并调用了 GetInstance。然而,我认为你的服务定位器没有设置正确,这就是为什么你会得到这个异常的原因。如果你正在使用 Prism 的 MefBootstrapper 来初始化你的应用程序,那么这已经为你完成了。否则,你需要使用以下代码来初始化:

IServiceLocator serviceLocator = new MefServiceLocatorAdapter(myCompositionContainer);
ServiceLocator.SetLocatorProvider(() => serviceLocator);

谢谢,服务定位器的初始化已经成功。但是当我使用import many属性[ImportMany(typeof(IMyInterface))]时,List属性总是为空。 - user2250152
它是空的,因为[ImportMany(typeof(IMyInterface))]只会导入那些没有契约名称导出的部件。 - Adi Lester
有没有办法通过契约名称导入使用importmany属性导出的部件? 因为在我的应用程序的一部分中,我需要使用实现给定接口的类集合工作,在另一部分中,我需要使用通过ServiceLocator.Current.GetInstance获得的具体类。 - user2250152
1
你有几个选项:1. 使用两个导出属性 - 一个带有合同名称,一个没有。这样,您将能够使用合同名称导入它们,这将提供单个实例,或者不使用合同名称导入它们,这将提供所有实例。2. 导出部件带元数据,并根据导出时定义的元数据选择特定实例。 - Adi Lester
尝试弄清楚为单元测试MEF控制的对象做哪些准备工作。在我的情况下,我还需要调用myCompositionContainer.ComposeExportedValue<IServiceLocator>(serviceLocator)。 - dudeNumber4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接