我对MEF比较新,所以我不完全了解这些功能。我正在努力实现与Unity的InjectionMember类似的东西。
假设我有一个导入MEF部件的类。为简单起见,我们将以下类作为导出部分的示例。
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Logger {
public string Category {
get;
set;
}
public void Write(string text) {
}
}
public class MyViewModel {
[Import]
public Logger Log {
get;
set;
}
}
现在我想弄清楚的是,是否可以在导入时为Category属性指定值。类似的东西:
public class MyViewModel {
[MyImportAttribute(Category="MyCategory")]
public Logger Log {
get;
set;
}
}
public class MyOtherViewModel {
[MyImportAttribute(Category="MyOtherCategory")]
public Logger Log {
get;
set;
}
}
目前,我正在做的是实现IPartImportsSatisfiedNotification并在代码中设置Category。但显然我宁愿将所有东西整齐地放在一个地方。
答案 0 :(得分:6)
在MEF programming guide中,请阅读Exports and Metadata部分。它显示了如何在导出的部件上添加元数据,方法是使用ExportMetadata
属性或定义自己的自定义导出属性。
然后,您可以像这样定义ILoggerMetadata
界面:
public interface ILoggerMetadata
{
string Catagory { get; }
}
并执行ImportMany
的{{1}}并在代码中选择您想要的那个:
IEnumerable<Lazy<ILogger,ILoggerMetadata>>
我同意将元数据约束直接放在import属性中更好,但目前在MEF开箱即用是不可能的。 (有可能扩展MEF来做到这一点。)
另一种方法是从private ILogger fooLogger;
[ImportMany]
public IEnumerable<Lazy<ILogger,ILoggerMetadata>> Loggers
{
set
{
this.fooLogger = value.First(x => x.Metadata.Catagory == "foo").Value;
}
}
派生IFooLogger
接口,并在导入和导出中使用它。这很简单,与将约束放在导入中的效果基本相同。但是,如果您有多个元数据属性和/或许多可能的值,则此方法不起作用。
编辑:我巧妙地误解了你的问题;我认为这是关于约束导入,而不是使用一些额外的参数配置导入的对象。
我认为Kathleen Dollard的this recent post也存在同样的问题。此外,在this post about component relationships中,Nicholas Blumhardt将这种“参数化”关系建模为注入ILogger
(或Func<X,Y>
)。
您可以通过直接在方法上放置Func<ILogger,string>
属性来在MEF中执行相同的操作。或者,如果您需要一个不那么模糊的合同,您可以定义一个[Export(typeof(Func<ILogger,string>))]
接口并导入/导出:
ILoggerFactory
最后,你仍然需要在代码中调用工厂。
答案 1 :(得分:3)
在进一步深入研究MEF之后,似乎没有办法以声明的方式做到这一点。虽然您可以派生自己的导出属性,但似乎没有任何机制可以以任何有意义的方式派生导入属性。
但是,不是实现IPartImportsSatisfiedNotification,我可以做的(现在看来很明显)是在setter中设置类别。我必须放弃自动财产,但这就是生命。
public class MyViewModel {
private Logger log;
[Import]
public Logger Log {
get { return log; }
set {
log = value;
log.Category = "MyCategory";
}
}
}