繁体   English   中英

更换零件时如何使MEF重新组成?

[英]How do I get MEF to recompose when I change a part?

我试图让MEF重组在更新导出的实例时它所知道的所有部分。 本质上,我想让MEF更新我的所有零件,这些零件在更改时会导入连接字符串配置值。 一切看起来都很好,直到我想更改实例为止。 如果我尝试使用更新的值来编写ComposeParts,则似乎在容器中添加了第二个零件实例,然后更新了我的导入,但将其更新为null。

谁能指出我要去哪里了? 还是我应该尝试以这种方式使用MEF?

我正在使用MEF预览9和目标.net框架3.5和WPF。

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using Shouldly;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            MainClass main = new MainClass();
            main.RunTest();
        }
    }

    public class MainClass
    {
        [ImportMany]
        public IEnumerable<Settings> Settings { get; set; }

        public void RunTest()
        {
            AggregateCatalog catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(typeof(Settings).Assembly));

            CompositionContainer container = new CompositionContainer(catalog);

            container.SatisfyImportsOnce(this);

            Config cfg = new Config
            {
                Settings = new Settings { ConnectionString = "Value1" },
            };

            // result is returned with a null settings value
            UsesSettings result = container.GetExportedValue<UsesSettings>();

            // this recomposes everything with the new value, result changes to have settings of Value1
            container.ComposeParts(cfg);

            // this line results in my import many enumerable returning 2 parts the Value1 setting and null
            container.SatisfyImportsOnce(this);

            result.TheSettings.ConnectionString.ShouldBe("Value1");

            cfg.Settings = new Settings { ConnectionString = "Value2" };

            // how do I tell the container to recompose now I have changed the config object,
            // or how do I replace the part value with the new value?

            // this line causes the result.Settings to return null
            container.ComposeParts(cfg);

            // this updates the ImportMany to 3 values, Value1, Value2 and null
            container.SatisfyImportsOnce(this);
        }
    }

    public class Settings
    {
        public string ConnectionString = "default value";
    }

    public class Config
    {
        [Export(typeof(Settings))]
        public Settings Settings { get; set; }
    }

    [Export(typeof(UsesSettings))]
    public class UsesSettings
    {
        [Import(typeof(Settings), AllowRecomposition = true)]
        public Settings TheSettings { get; set; }
    }
}

对于要完成的方案,您还有一些不足之处。

首先:如果要添加/删除/更改特定的导出,则它一定不能出现在目录本身中,因此应删除具有“导出设置”属性的Config类。 这是由CatalogExportProvider创建的,这是在集合中看到空值的原因。

请尝试以下操作:

public class Program
{
    [ImportMany(AllowRecomposition=true)]
    public IEnumerable<Settings> Settings { get; set; }

    public void RunTest()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Settings).Assembly));

        CompositionContainer container = new CompositionContainer(catalog);

        // Settings should have 0 values.
        container.ComposeParts(this);
        Contract.Assert(this.Settings.Count() == 0);

        CompositionBatch batch = new CompositionBatch();

        // Store the settingsPart for later removal...
        ComposablePart settingsPart = 
            batch.AddExportedValue(new Settings { ConnectionString = "Value1" });

        container.Compose(batch);

        // Settings should have "Value1"
        UsesSettings result = container.GetExportedValue<UsesSettings>();
        Contract.Assert(result.TheSettings.ConnectionString == "Value1");

        // Settings should have 1 value which is "Value1";
        Contract.Assert(this.Settings.Count() == 1);
        Contract.Assert(this.Settings.First().ConnectionString == "Value1");

        // Remove the old settings and replace it with a new one.
        batch = new CompositionBatch();
        batch.RemovePart(settingsPart);
        batch.AddExportedValue(new Settings { ConnectionString = "Value2" });
        container.Compose(batch);

        // result.Settings should have "Value2" now.
        Contract.Assert(result.TheSettings.ConnectionString == "Value2");

        // Settings should have 1 value which is "Value2"
        Contract.Assert(this.Settings.Count() == 1);
        Contract.Assert(this.Settings.First().ConnectionString == "Value2");
    }
}
public class Settings
{
    public string ConnectionString = "default value";
}

[Export(typeof(UsesSettings))]
public class UsesSettings
{
    [Import(typeof(Settings), AllowRecomposition = true)]
    public Settings TheSettings { get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM