2015-02-05 6 views
0

Предположим, у меня есть интерфейс ITest:ServiceLocator GetAllInstances не содержит экземпляр которого контракт имя указано

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, независимо от того, какая реализация имеет экспортированное имя контакта?

ответ

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 { }