【问题标题】:Prism ServiceLocator GetInstance and MEFPrism ServiceLocator GetInstance 和 MEF
【发布时间】:2023-03-09 13:39:01
【问题描述】:

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

我有两个实现接口 IMyInterface 的类,它们具有 Export 属性:
[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");

但我不知道应该如何以及在哪里定义“关键”。我试图在导出属性中定义键:

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

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

当我使用 key 参数调用方法 GetInstance 时

ServiceLocator.Current.GetInstance(typeof(IMyInterface),"Key1");

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

【问题讨论】:

    标签: c# prism mef


    【解决方案1】:

    Prism 使用MefServiceLocatorAdapter 将MEF 的CompositionsContainer 适配到IServiceLocator 接口。这是它用来获取您的部分的实际代码:

    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 attribute [ImportMany(typeof(IMyInterface))] public IEnumerable List { get;放; } List 属性总是空的。
    • 它是空的,因为[ImportMany(typeof(IMyInterface))] 只会导入没有合同名称导出的部分。
    • 还有什么方法可以导入带有 importmany 属性的零件,这些零件是用合同名称导出的?因为在我的应用程序的一部分中,我需要使用实现给定接口的类的集合,而在另一部分中,我需要使用通过 ServiceLocator.Current.GetInstance 获得的具体类。
    • 这里有几个选项: 1. 使用两个导出属性 - 一个带有合同名称,一个没有。这样,您将能够使用合同名称导入它们,这将给出一个实例,或者没有合同名称,这将给出所有实例。 2.导出部件with metadata,根据导出时定义的元数据选择具体实例。
    • 试图弄清楚在准备单元测试 MEF 受控对象时要做什么。就我而言,我必须另外调用 myCompositionContainer.ComposeExportedValue( serviceLocator );
    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2011-05-08
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多