在MEF中覆盖子容器中的导出

时间:2018-03-16 10:57:08

标签: c# containers mef

我们在大型WPF应用程序中使用MEF进行依赖注入。在MEF容器中,我们注册了一个共享实例( MyPriceProvider ),它提供了一些在某些计算中使用的数据。

我想并行化这些计算,但每次计算都会改变 MyPriceProvider 中的数据。因此,运行计算的每个线程都必须拥有自己的 MyPriceProvider 实例。

我为每个线程创建一个子容器,并在每个子容器中用新实例覆盖 MyPriceProvider

但是,当我从子容器中解析 MyCalculator 时,会创建一个对根容器中 MyPriceProvider 的共享实例的引用。

鉴于这两个类 MyCalculator MyPriceProvider

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MyCalculator
{
    private readonly MyPriceProvider _priceProvider;

    public MyPriceProvider PriceProvider => _priceProvider;

    [ImportingConstructor]
    public MyCalculator(MyPriceProvider priceProvider)
    {
        _priceProvider = priceProvider;
    }
}

[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyPriceProvider
{

}

这是一个简单的程序来重现这个问题:

 public static void Main(string[] args)
    {
        // Create root container:
        var aggregateCatalog = new AggregateCatalog();
        var composablePartCatalog = new DirectoryCatalog(".", "*.exe");
        aggregateCatalog.Catalogs.Add(composablePartCatalog);

        var catalogProvider = new CatalogExportProvider(aggregateCatalog);

        var rootContainer = new CompositionContainer(catalogProvider);
        catalogProvider.SourceProvider = rootContainer;

        // Resolve shared MyPriceProvider from root:
        var priceProviderFromRoot = rootContainer.GetExportedValue<MyPriceProvider>();

        // Create child container with single ExportProvider (rootContainer)
        var childContainer = new CompositionContainer(rootContainer);

        // Overwrite MyPriceProvider in child container
        var myPriceProvider = new MyPriceProvider();
        childContainer.ComposeExportedValue(myPriceProvider);

        // Resolve MyCalculator from child Container
        var calculatorFromChildProvider = childContainer.GetExportedValue<MyCalculator>();
        if (calculatorFromChildProvider.PriceProvider ==  priceProviderFromRoot)
        {
            // PriceProvider resolved from MyCalculator is shared instance from root container, NOT the overwritten instance.
        }
    }

我相信我明白为什么 MyCalculator 会获取对 MyPriceProvider 的共享实例的引用,因为 MyCalculator 已在根容器中注册,以及何时MEF正在解析它的依赖关系,它不知道在子容器中覆盖了 MyPriceProvider

我无法以任何方式更改根容器,因为我将创建多个子容器以供并行使用,并且所有容器都将共享相同的根容器。

我有什么方法可以配置子容器,以便 MyCalculator 在从子容器中解析时获取被覆盖的实例?

0 个答案:

没有答案