ServiceLocator GetAllInstances不包含指定了合同名称的实例

时间:2015-02-05 06:21:54

标签: c# mef service-locator common-service-locator

假设我有一个接口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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

根据MSDN,第三个参数是

  

contractName :要返回的Lazy对象的合约名称,或 null 或空字符串(&#34;&#34) ;)使用默认合同名称。

正如您在本主题的评论中所看到的那样:

  

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

该默认合约名称基于完整类型名称,不含任何其他键。这就是为什么你只得到第二个导出:它有默认的合同名称。

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

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

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

[Export(typeof(ITest))]
[ExportMetadata("Type", string.Empty)]
public class Test2 : ITest { }