0

假设我有一个界面ITest

public interface ITest
{
    void PrintMachineInfo();
}

再加上两个实现:

[Export("MachineName", typeof(ITest))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class Test1 : ITest
{
    public void PrintMachineInfo()
    {
        Console.WriteLine(Environment.MachineName);
    }
}

[Export(typeof(ITest))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class Test2 : ITest
{
    public void PrintMachineInfo()
    {
        Console.WriteLine(Environment.OSVersion);
    }
}

然后,我尝试检索以下所有实例ITest

var foo = ServiceLocator.Current.GetAllInstances<ITest>();
foreach (var test in foo)
{
    test.PrintMachineInfo();
}

事实证明,只能Test2返回实例。由于合同名称,它只是找不到Test1.

我使用 MEF + ServiceLocator + MefAdapter来运行所有这些东西。从我的调试来看,MefAdapter 覆盖了 中的方法DoGetAllInstances(Type serviceType)ServiceLocatorImplBase但它只提供了一个参数serviceType

ITest那么,无论实现是否导出了联系人姓名,如何使用 ServiceLocator获取所有实例?

4

1 回答 1

0

IServiceLocator使用Prism 提供的当前实现是不可能实现您想要的。

该实现中的重写DoGetAllInstances()方法调用该GetExport()方法的最后一个重载:

this.compositionContainer.GetExports(serviceType, null, null);

根据MSDN,第三个参数是

contractName:要返回的 Lazy 对象的合约名称,或者null或空字符串 ("") 以使用默认合约名称。

正如您在对该主题的评论中看到的:

默认合约名称是对类型调用 GetContractName 方法的结果。

该默认合同名称基于完整的类型名称,没有任何附加键。这就是为什么您只获得第二个导出:它具有默认合同名称。

因此,如果不完全了解所有合约密钥,就无法以这种方式获得所有导出。

要提供多个导出同时能够区分它们,您可以为每个导出提供额外的元数据并保留相同的导出合同名称:

[Export(typeof(ITest))]
[ExportMetadata("Type", "MachineName")]
public class Test1 : ITest { }

[Export(typeof(ITest))]
[ExportMetadata("Type", string.Empty)]
public class Test2 : ITest { }
于 2015-02-24T13:02:07.753 回答