0

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 中做到这一点?

4

4 回答 4

1

如果不想使用属性,可以使用这个技巧(基于Mark Seemann 的博文)。

首先,创建一个像这样的泛型类:

[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);
于 2011-09-09T13:58:28.057 回答
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来添加对此的支持。

于 2011-09-09T12:08:30.803 回答
0

两个实例都是一样的。如何强制(配置)它们为不同的实例?

只需像这样标记SomeThing类:

[Export(typeof(ISomeThing)]
[PartCreationPolicy(CreationPolicy.NonShared]
public class SomeThing : ISomeThing
{
   ...
}

然后无论你在哪里 import 都会得到不同的实例ISomeThing

或者,您还可以在导入时设置所需的创建策略:

[Export(typeof(IFoo))]
public class Foo : IFoo
{
   [Import(typeof(ISomeThing), 
       RequiredCreationPolicy = CreationPolicy.NonShared)]
   public ISomething SomeThing { private get; set; }

}
于 2011-09-09T13:44:20.997 回答
0

在与Matthew Abbott 的回答链接的 Glen Block 的 Skydrive 目录中,我发现了一些看似简单且轻量级的东西:A 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>();
于 2011-09-09T13:46:48.640 回答