繁体   English   中英

带元数据的MEF GetExportedValue

[英]MEF GetExportedValue with metadata

我想在我的项目中使用MEF作为DI。 我有一个项目,每个应该编写的类都驻留在那里(它们共享一个接口)。 现在我想通过指定元数据值来创建其中一个。 这是定义:

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

现在我想通过MEF创建一个TestReader1实例,但我不知道如何通过CompositionContainer按元数据进行过滤。 我想要类似的东西

Container.GetExportedValue<IGatewayResponseReader>();

但要指定元数据以选择要创建的类实例。

非常感谢您的帮助。

谢谢。

@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属性之前检查导入是否为null是个好主意:

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( ... );
    }
}
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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM