cli*_*cky 3 c# mef composition
我有一个接口的多种实现,并且我只想以编程方式导出一个。我已经看过了RegistrationBuilder,它的AddMetaData()功能是,但这是为导出定义MetaData,而不是为特定值过滤。例如,我想做这样的事情:
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.
Run Code Online (Sandbox Code Playgroud)
+1的问题-自从4.5出现以来,我再也没有机会看过MEF,所以这迫使我不得不加快学习新RegistrationBuilder课程的速度!
我猜测您的示例不起作用的原因是,据我了解,该示例RegistrationBuilder旨在取代MEF在.NET 4.0之前非常依赖的属性的角色。这ExportMetadataAttribute是旧的做事方式的一部分,只是我的猜测,旧的和新的不能很好地结合在一起。
多亏了RegistrationBuilder您的加入,您可以完全实现所需的功能,而导出的类却不知道它们是使用MEF构造的。在我看来,这是从4.0开始的MEF的巨大改进。
首先让我们从要导出的类开始。首先,我定义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; }
}
Run Code Online (Sandbox Code Playgroud)
现在来看我可能要导出的类:
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
解决问题的关键是上的ForTypesMatching()方法RegistrationBuilder。该参数是一个谓词,该谓词采用类型并根据要在导出结果中包括类型而返回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; }
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4065 次 |
| 最近记录: |