在Funq和大多数其他IoC容器中,我可以简单地这样做来配置类型:
container.Register<ISomeThing>(c => new SomeThing());
如何在不使用属性的情况下快速扩展MEF(或使用现有的MEF功能)来做同样的事情。
以下是我认为我能做到的事情:
var container = new CompositionContainer();
var batch = new CompositionBatch();
batch.AddExport<ISomeThing>(() => new SomeThing());
batch.AddExportedValue(batch);
container.Compose(batch);
使用此CompositionBatch
的扩展方法:
public static ComposablePart AddExport<TKey>(this CompositionBatch batch, Func<object> func)
{
var typeString = typeof(TKey).ToString();
return batch.AddExport(
new Export(
new ExportDefinition(
typeString,
new Dictionary<string, object>() { { "ExportTypeIdentity", typeString } }),
func));
}
如果我以后再做:
var a = container.GetExport<ISomeThing>().Value;
var b = container.GetExport<ISomeThing>().Value;
两个实例都是一样的。如何强制(配置)它们为不同的实例?
如果这不是可行的方法,我将如何在MEF中执行此操作?
答案 0 :(得分:1)
我认为关键是将委托添加到容器中,例如:
container.AddExportedValue<Func<ISomething>>(() => new Something());
这样你就可以抓住委托并执行它:
var factory = container.GetExport<Func<ISomething>>();
ISomething something = factory();
当然,MEF(Silverlight)确实提供了一个原生ExportFactory<T>
(和ExportFactory<T,TMetadata>
类型,支持为每个要导入的调用创建新实例。您可以通过下载Glen Block来添加对此的支持。 ExportFactory for .NET 4.0 (Desktop) library
答案 1 :(得分:1)
如果您不想使用属性,可以使用此技巧(基于Mark Seemann's blogpost)。
首先,创建一个这样的泛型类:
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MefAdapter<T> where T : new()
{
private readonly T export;
public MefAdapter()
{
this.export = new T();
}
[Export]
public virtual T Export
{
get { return this.export; }
}
}
现在,您可以在容器中注册所需的任何类,如下所示:
var registeredTypesCatalog = new TypeCatalog(
typeof(MefAdapter<Foo>),
typeof(MefAdapter<Bar>),
...);
var container = new CompositionContainer(catalog);
或者,您可以实现从ExportProvider派生的自己的导出提供程序,这使您可以轻松复制Funq的工作方式:
var provider = new FunqyExportProvider();
provider.Register<IFoo>(context => new Foo());
var container = new CompositionContainer(provider);
答案 2 :(得分:0)
两个实例都是一样的。如何强制(配置)它们为不同的实例?
只需将SomeThing
类标记为:
[Export(typeof(ISomeThing)]
[PartCreationPolicy(CreationPolicy.NonShared]
public class SomeThing : ISomeThing
{
...
}
然后,只要导入ISomeThing
,就会得到不同的实例。
或者,您也可以在导入时设置所需的创建策略:
[Export(typeof(IFoo))]
public class Foo : IFoo
{
[Import(typeof(ISomeThing),
RequiredCreationPolicy = CreationPolicy.NonShared)]
public ISomething SomeThing { private get; set; }
}
答案 3 :(得分:0)
在Glen Block的链接到Matthew Abbott's answer的Skydrive目录中,我找到了一些看似简单轻巧的东西:FuncCatalog
。在此处下载:FuncCatalogExtension。
使用该项目中的几个小班,我现在可以这样做:
var funcCatalog = new FuncCatalog();
funcCatalog.AddPart<ISomeThing>(ep => new SomeThing());
var container = new CompositionContainer(funcCatalog);
var batch = new CompositionBatch();
batch.AddExportedObject<ExportProvider>(container);
container.Compose(batch);
var a = container.GetExportedObject<ISomeThing>();
var b = container.GetExportedObject<ISomeThing>();