MEF GetExportedValue с метаданными - PullRequest
       0

MEF GetExportedValue с метаданными

5 голосов
/ 26 августа 2011

Я хочу использовать MEF в качестве DI для моего проекта.У меня есть 1 проект, и все классы, которые должны быть составлены, находятся там (они имеют один интерфейс).Теперь я хочу создать один из них, указав значение метаданных.Вот определения:

public interface IGatewayResponseReader
{
    object Read(string msg);
}

[Export(typeof(IGatewayResponseReader))]
[ExportMetadata(G3Reader.META_KEY, "value1")]
public class TestReader1 : IGatewayResponseReader
{
    ...
}

[Export(typeof(IGatewayResponseReader))]
[ExportMetadata(G3Reader.META_KEY, "value2")]
public class TestReader2 : IGatewayResponseReader
{
    ...
}

Теперь я хочу создать экземпляр TestReader1 через MEF, но я не знаю, как фильтровать по метаданным через CompositionContainer.Я хочу что-то вроде

Container.GetExportedValue<IGatewayResponseReader>();

Но указать метаданные, чтобы выбрать, какой экземпляр класса создать.

Ваша помощь очень ценится.

Спасибо.

Ответы [ 2 ]

6 голосов
/ 26 августа 2011

Ответ, предоставленный @Dmitry Ornatsky, верен, но предпочтительным способом предоставления метаданных экспорта является использование строго типизированных метаданных с использованием пользовательского атрибута экспорта:

public interface IGatewayResponseReaderMetadata
{
    string Key { get; }
}

[MetadataAttribute]
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Property )]
public class GatewayResponseReaderExportAttribute : ExportAttribute
{
    public GatewayResponseReaderExportAttribute( string key )
        : base( typeof( IGatewayResponseReader ) )
    {
        this.Key = key;
    }

    public string Key { get; set; }
}

[GatewayResponseReaderExport("value1")]
public class TestReader1 : IGatewayResponseReader
{
}

Код для поиска импорта можно сделать безопасным для типов. Обратите внимание, что перед тем, как получить доступ к свойству Value, рекомендуется проверить, не является ли импорт недействительным:

class Program
{
    [ImportMany]
    private List<Lazy<IGatewayResponseReader, IGatewayResponseReaderMetadata>> _readers;

    static void Main( string[] args )
    {
        CompositionContainer container = new CompositionContainer( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );

        Program program = new Program();
        container.SatisfyImportsOnce( program );


        var reader = program._readers.FirstOrDefault( r => r.Metadata.Key == "value1" );
        if ( reader != null )
            reader.Value.Read( ... );
    }
}
4 голосов
/ 26 августа 2011
class Program
{
    [ImportMany]
    private List<Lazy<IGatewayResponseReader, IDictionary<string, object>>> _readers;

    static void Main(string[] args)
    {
        CompositionContainer container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

        Program program = new Program();
        container.SatisfyImportsOnce(program);
        var result = program._readers.Where(r =>            
            r.Metadata.ContainsKey(G3Reader.META_KEY) && (string)r.Metadata[G3Reader.META_KEY] == "value1")
            .First().Value;
    }
}
...