我的MEF导出如下:
public interface IMyInterface { }
public interface IInterfaceData
{
string[] Data { get; }
}
[Export("MyContractName", typeof(IMyInterface))]
[ExportMetadata("Data", "SomeData", IsMultiple = true)]
public class MyInterfaceClass : IMyInterface { }
然后我使用导入:
public class MyClass {
[ImportMany("MyContractName", typeof(IMyInterface))]
private IEnumerable<Lazy<IMyInterface, IInterfaceData>> _operations;
private CompositionContainer _container;
private void Compose() {
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
}
这很好用。但是,我希望能够使用基于当前正在执行的业务逻辑的合同名称在运行时撰写我的Imports。换句话说,我希望能够导入变量合同名称。我可以这样做:
private void Compose() {
var contractName = "MyContractName"; // note this would be determined at run-time
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_container = new CompositionContainer(catalog);
var foundExports = _container.GetExports<IMyInterface, IInterfaceData>(contractName);
_operations = foundExports; // set manually
}
我非常乐意接受这个*。但是,现在没有[ImportMany]
属性的原因,我再也无法使用ComposeParts()
。我想在整个项目中保持一致(为了我和我的团队),并且希望能够依赖MEF属性,Compose()
/ ComposeParts()
或两者。
是否有其他方法可以定义Import
属性,以便调用_container.Compose()
会考虑运行时定义的合同名称?也许导出需要改变,或者MEF框架中有其他东西可供我使用(属性明智)?
*我不确定这是否“正确”。即使它 工作。如果我试图让所有事情保持一致,那只会感到草率。
答案 0 :(得分:2)
这可以通过直接在容器上使用CompositionBatch
来完成。
var batch = new CompositionBatch();
// Add the export to the batch via method or object referebce
batch.AddExport(new Export(name, partFactory));
batch.AddExport(new Export(part.Name, () => part));
// Compose into your CompositionContainer
_container.Compose(batch);
private MyClass PartFactory()
{
// TODO: create the part to export..
}
请注意,对于container
对象,可以在构造期间使用CompositionOptions.ExportCompositionService
导出容器本身,从而允许
[Import] CompositionContainer _container;