我如何获得MEF以重新当我改变的一部分? [英] How do I get MEF to recompose when I change a part?

查看:126
本文介绍了我如何获得MEF以重新当我改变的一部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获得MEF以重新所有它知道,当我更新导出一个实例的部分。基本上我想有MEF更新我的所有部件进口的连接字符串配置值,当它被改变。一切看起来好起来的地方,我想改变实例的点。如果我尝试ComposeParts的值更新它似乎添加第二个部分实例放入容器内,然后我的进口被更新,但空。

任何人都可以指出我要去的地方错了?或者我应该甚至可以尝试使用MEF以这种方式?

我使用MEF preVIEW 9和目标定位的.NET Framework 3.5和WPF。

 使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.Composition;
使用System.ComponentModel.Composition.Hosting;
使用System.Linq的;
使用System.Text;
使用Shouldly;

命名空间ConsoleApplication4
{
    类节目
    {
        静态无效的主要(字串[] args)
        {
            MainClass主要=新MainClass();
            main.RunTest();
        }
    }

    公共类MainClass
    {
        [ImportMany]
        公开的IEnumerable<设置>设置{获得;组; }

        公共无效的runTest()
        {
            AggregateCatalog目录=新AggregateCatalog();
            catalog.Catalogs.Add(新AssemblyCatalog(typeof运算(设置).Assembly));

            CompositionContainer中集装箱=新CompositionContainer中(目录);

            container.SatisfyImportsOnce(本);

            配置CFG =新配置
            {
                设置=新设置{的ConnectionString =值1},
            };

            //结果与空设置返回值
            UsesSettings导致= container.GetExportedValue< UsesSettings>();

            //这个重新组成所有新值,结果变为有值1的设置
            container.ComposeParts(CFG);

            //此行会导致我进口很多枚举返回2份值1设置和空
            container.SatisfyImportsOnce(本);

            result.TheSettings.ConnectionString.ShouldBe(值1);

            cfg.Settings =新设置{的ConnectionString =值2};

            //我怎么告诉容器现在重构我已经改变了配置对象,
            //或者我怎么更换部件的价值与新的价值?

            //此行会导致result.Settings返回空
            container.ComposeParts(CFG);

            //这个更新ImportMany至3个值,值1,值2和空
            container.SatisfyImportsOnce(本);
        }
    }

    公共类设置
    {
        公共字符串的ConnectionString =默认值;
    }

    公共类配置
    {
        [导出(typeof运算(设置))]
        公共场所设置{获得;组; }
    }

    [导出(typeof运算(UsesSettings))]
    公共类UsesSettings
    {
        [进口(typeof运算(设置),AllowRecomposition =真)
        公共设置TheSettings {获得;组; }
    }
}
 

解决方案

您有几件事情有点过了,你所要完成的场景。

第一:如果你想添加/删除/更改特定出口也不得在目录本身,所以你应该删除其中有导出设置属性的配置类。这正由CatalogExportProvider创建,是你看到在您的收藏null值的原因。

请尝试以下操作:

 公共类节目
{
    [ImportMany(AllowRecomposition =真)
    公开的IEnumerable<设置>设置{获得;组; }

    公共无效的runTest()
    {
        AggregateCatalog目录=新AggregateCatalog();
        catalog.Catalogs.Add(新AssemblyCatalog(typeof运算(设置).Assembly));

        CompositionContainer中集装箱=新CompositionContainer中(目录);

        //设置应该有0值。
        container.ComposeParts(本);
        Contract.Assert(this.Settings.Count()== 0);

        CompositionBatch批=新CompositionBatch();

        //存放settingsPart供以后拆除...
        ComposablePart settingsPart =
            batch.AddExportedValue(新设置{的ConnectionString =值1});

        container.Compose(批);

        //设置应该有值1
        UsesSettings导致= container.GetExportedValue< UsesSettings>();
        Contract.Assert(result.TheSettings.ConnectionString ==值1);

        //设置应该有1值,它是值1;
        Contract.Assert(this.Settings.Count()== 1);
        Contract.Assert(this.Settings.First()的ConnectionString ==值1);

        //删除旧的设置,并用更换一个新的。
        一批=新CompositionBatch();
        batch.RemovePart(settingsPart);
        batch.AddExportedValue(新设置{的ConnectionString =值2});
        container.Compose(批);

        // result.Settings应该有值2了。
        Contract.Assert(result.TheSettings.ConnectionString ==值2);

        //设置应该有1值,它是值2
        Contract.Assert(this.Settings.Count()== 1);
        Contract.Assert(this.Settings.First()的ConnectionString ==值2);
    }
}
公共类设置
{
    公共字符串的ConnectionString =默认值;
}

[导出(typeof运算(UsesSettings))]
公共类UsesSettings
{
    [进口(typeof运算(设置),AllowRecomposition =真)
    公共设置TheSettings {获得;组; }
}
 

I am trying to get MEF to recompose all the parts that it knows about when I update an instance that is exported. Essentially I want to have MEF update all my parts that import a connection string configuration value when it is changed. Everything looks good up to the point where I want to change the instance. If I try to ComposeParts with the value updated it seems to add a second part instance into the container, and then my imports are updated, but to null.

Can anyone point out where I am going wrong? Or should I even be trying to use MEF in this fashion?

I am using MEF preview 9 and targetting .net framework 3.5, and 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; }
    }
}

解决方案

You have a few things a little off for the scenario you are trying to accomplish.

First: If you want to add/remove/change a particular export it must not be in the catalog itself so you should remove your Config class which has the Export settings property. That is being created by the CatalogExportProvider and is the reason you are seeing a null value in your collection.

Try the following:

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; }
}

这篇关于我如何获得MEF以重新当我改变的一部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆