gpt4 book ai didi

c# - MEF RegistrationBuilder 导出特定接口(interface)实现

转载 作者:行者123 更新时间:2023-11-30 14:31:37 26 4
gpt4 key购买 nike

我有一个接口(interface)的多个实现,我想以编程方式只导出一个。我查看了 RegistrationBuilder 和它的 AddMetaData() 函数,但这是为导出定义元数据,而不是针对特定值进行过滤。例如,我想做这样的事情:

public enum MyClassType { TypeA, TypeB }
public interface IClass {}
public interface ClassMetaData { MyClassType Type { get; } }

[ExportMetadata("Type", MyClassType.TypeA)]
public MyClassA : IClass
{
public MyClassType Type { get { return MyClassType.TypeA; } }
}

[ExportMetadata("Type", MyClassType.TypeB)]
public MyClassB : IClass
{
public MyClassType Type { get { return MyClassType.TypeB; } }
}

//...Then in my bootstrapping class where I set up the MEF container...

var registrationBuilder = new RegistrationBuilder();
registrationBuilder.ForTypesDerivesFrom<IClass>()....
// How do I specify a filter in ^ to say only export the implementation with MetaData.Type == MyClassA or instance.Type == MyClassA.

最佳答案

+1 问题 - 自从 4.5 发布以来,我一直没有机会了解 MEF,所以它迫使我跟上新添加的 RegistrationBuilder 类的速度!

我猜您的示例不起作用的原因是因为据我了解,RegistrationBuilder 旨在取代 MEF 在 .NET 4.0 之前如此严重依赖的属性的作用. ExportMetadataAttribute 是旧方法的一部分,我只是猜测新旧方法不能很好地结合在一起。

由于添加了 RegistrationBuilder,您可以准确地实现您想要的,而无需导出的类知道它们是使用 MEF 构建的。在我看来,这是 MEF 相对于 4.0 的巨大改进。

首先让我们从要导出的类开始。首先,我定义了 MyMetadataAttribute 类,它封装了与我们要过滤的类型相关联的元数据:

public enum MyClassType
{
TypeOne,
TypeTwo
}

[AttributeUsage(AttributeTargets.Class)]
public class MyMetadataAttribute: Attribute
{
public MyMetadataAttribute(MyClassType type)
{
Type = type;
}

public MyClassType Type { get; private set; }
}

现在是我可能想要导出的类:

public interface IClass
{
}

[MyMetadata(MyClassType.TypeOne)]
public class MyClassA : IClass
{
public MyClassType Type
{
get { return MyClassType.TypeOne; }
}
}

[MyMetadata(MyClassType.TypeTwo)]
public class MyClassB : IClass
{
public MyClassType Type
{
get { return MyClassType.TypeTwo; }
}
}

解决问题的关键是 RegistrationBuilder 上的 ForTypesMatching() 方法。参数是一个谓词,它采用类型并返回 true 或 false,具体取决于您是否要在导出的结果中包含该类型。下面的代码演示了一个例子:

internal class Program
{
private static void Main(string[] args)
{
var registrationBuilder = new RegistrationBuilder();
registrationBuilder
.ForTypesMatching<IClass>(t => FilterOnMetadata(t, MyClassType.TypeOne))
.ExportInterfaces();
var assemblyCatalog = new AssemblyCatalog(typeof (MyClassType).Assembly, registrationBuilder);
var compositionContainer = new CompositionContainer(assemblyCatalog);
var ic = new TestImportContainer();
compositionContainer.ComposeParts(ic);
var count = ic.ImportedParts.Count();
}

public static bool FilterOnMetadata(Type t, MyClassType classType)
{
var metadataAttribute =
(MyMetadataAttribute) t.GetCustomAttributes(true)
.SingleOrDefault(at => at is MyMetadataAttribute);
if (metadataAttribute != null)
return metadataAttribute.Type == classType;
return false;
}

private sealed class TestImportContainer
{
[ImportMany(typeof(IClass))]
public IEnumerable<IClass> ImportedParts { get; set; }
}
}

关于c# - MEF RegistrationBuilder 导出特定接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19681374/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com