自定义“ExportFactory”

发布于 2024-10-07 03:41:08 字数 624 浏览 5 评论 0原文

使用 MEF 的桌面应用程序导入许多“ServiceProviders”。每个部分(ServiceProvider)都是一个单独的 DLL 中的类。 所有 DLL 都位于桌面应用程序使用的“Plugin”文件夹中。

由于我需要部件的新实例,ExportFactory 是最佳选择。问题是我的部件有构造函数。我需要传递一些参数到 ExportFactory 不支持的部件的构造函数中(MEF2,Preview2)

我需要这样的东西:

// Each part has its own dependency
Dependency dependency = LoadDependency(myPart.Metedata["Name"]);
// Injecting dependency into part's constructor
myPart.CreateExport(dependency);

我不想从我的部件端导入任何东西(

带有参数-) 。 less 构造函数)可以在此处找到。

A desktop application using MEF imports many 'ServiceProviders'. Each part (ServiceProvider) is a class inside a separate DLL.
All DLLs are in 'Plugin" folder which is used by desktop application.

Since I needed new Instances of my parts, ExportFactory was the best choice. The problem is my parts have constructors. I need pass some parameters into constructor of the part which is not supported by ExportFactory (MEF2, Preview2).

I need something like this:

// Each part has its own dependency
Dependency dependency = LoadDependency(myPart.Metedata["Name"]);
// Injecting dependency into part's constructor
myPart.CreateExport(dependency);

I don't want import anything from my parts-side.

A sample project (with parameter-less constructor) can be found here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜柠檬 2024-10-14 03:41:08

当 MEF 看到 ExportFactory 类型的导入时,它会以特殊方式处理它。它不是逐字查找 ExportFactory 导出,而是查找 IFoo 导出并神奇地生成该类型的工厂。

您的错误是您希望这种魔法也能自动用于您自己的 ExportFactory 替代方案(您称为 SrviceProviderFactory)。这不是真的。当您在某处导入 SrviceProviderFactory 时,MEF 实际上会查找该类型的导出。

最简单的解决方案是为其提供此导出。为每个 IServiceProvider 实现手动导出工厂。例如,如果您有一个 FooServiceProvider:

public class FooServiceProvider : IServiceProvider
{
    public FooServiceProvider(Dependency dependency)
    {
        ...
    }
}

那么您还需要有一个 FooServiceProviderFactory:

[Export(typeof(IServiceProviderFactory))]
[ExportMetaData("foo", "bar")]
public class FooServiceProviderFactory : IServiceProviderFactory
{
    public IServiceProvider CreateServiceProvider(Dependency d)
    {
       return new FooServiceProvider(d);
    }
}

然后您的导入程序可以根据元数据选择正确的工厂:

public class FactoryUser
{
    [ImportMany]
    public Lazy<IServiceProviderFactory,IDictionary<string,object>>[] Factories 
    {
        get;
        set;
    }

    public void DoSomething()
    {
       var factory = Factories.First(x => x.Metadata["foo"] == "bar").Value;
       var serviceProvider = factory.CreateServiceProvider(someDependency);
       ...
    }
}

这里烦人的是,对于每个服务提供者实现,您还需要创建并导出工厂实现。您可以通过创建通用工厂基类(例如 SrviceProviderFactory)来节省工作量,但您仍然必须派生特定的类,因为您无法在 MEF 导出中使用泛型类型参数。 更新:我相信.NET 4.5现在支持导出开放泛型类型。

这就是为什么 我已经建议您导出 Func 而不是,但显然您不喜欢这个答案。

您还可以尝试复制 ExportFactory 魔法。这是可能的,但这是 MEF 的一个非常高级的用例。如果您想这样做,我建议您查看 ExportFactoryProvider 的 MEF 源,了解如何构建您自己的支持参数的实现。

When MEF sees an import of the type ExportFactory<IFoo>, it treats this in a special way. Instead of looking literally for an ExportFactory<IFoo> export, it looks instead for a IFoo export and magically generates a factory for that type.

Your mistake is that you expect this magic to also automatically work for your own alternative to ExportFactory which you called SrviceProviderFactory. This is not true. When you import SrviceProviderFactory<IFoo,IFooMetadata> somewhere, MEF literally looks for an export of that type.

The straightforward solution is to give it this export. Manually export a factory for each IServiceProvider implementation. For example, if you have a FooServiceProvider:

public class FooServiceProvider : IServiceProvider
{
    public FooServiceProvider(Dependency dependency)
    {
        ...
    }
}

Then you also need to have a FooServiceProviderFactory:

[Export(typeof(IServiceProviderFactory))]
[ExportMetaData("foo", "bar")]
public class FooServiceProviderFactory : IServiceProviderFactory
{
    public IServiceProvider CreateServiceProvider(Dependency d)
    {
       return new FooServiceProvider(d);
    }
}

And then your importer can select the right factory based on metadata:

public class FactoryUser
{
    [ImportMany]
    public Lazy<IServiceProviderFactory,IDictionary<string,object>>[] Factories 
    {
        get;
        set;
    }

    public void DoSomething()
    {
       var factory = Factories.First(x => x.Metadata["foo"] == "bar").Value;
       var serviceProvider = factory.CreateServiceProvider(someDependency);
       ...
    }
}

The annoying thing here is that for each service provider implementation, you also need to create and export a factory implementation. You can save work by creating a common factory base class (like your SrviceProviderFactory) but you still have to derive specific classes because you can't use generic type parameters in MEF exports. update: I believe .NET 4.5 now supports exporting open generic types.

That's why I already suggested you export Func instead, but apparently you didn't like that answer.

You could also try to replicate the ExportFactory magic. This is possible but a very advanced use case of MEF. If you want to do that I suggest you take a look at the MEF sources of ExportFactoryProvider to see how to build your own implementation with support for parameters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文