MEF GetExportedValue 与元数据

发布于 2024-12-01 19:53:31 字数 718 浏览 0 评论 0原文

我想使用 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
{
    ...
}

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

Container.GetExportedValue<IGatewayResponseReader>();

But 的东西来指定元数据来选择要创建的类实例。

非常感谢您的帮助。

谢谢。

I want to use MEF as a DI for my project. I have 1 project and every classes that should be composed resides there (they share one interface). Now I want to create one of them by specifiyng a metadata value. Here's the definitions:

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

Now I want to create an instance of TestReader1 through MEF, but I don't know how to filter by metadata through CompositionContainer. I want something like

Container.GetExportedValue<IGatewayResponseReader>();

But to specify the metadata to choose which class instance to create.

Your help is much appreciated.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乖不如嘢 2024-12-08 19:53:31

@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 属性之前检查 import 是否不为 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( ... );
    }
}

The answer provied by @Dmitry Ornatsky is correct, but the preferred way of providing export metadata is to use strongly-typed metadata using a custom export attribute:

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

The code to look up an import can then be made type-safe. Note that it's a good idea to check if import is not null before accessing the Value property:

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( ... );
    }
}
娜些时光,永不杰束 2024-12-08 19:53:31
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;
    }
}
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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文