MEF初体验之十:部件重组

一些应用程序被设计成在运行时可以动态改变。例如,一个新的扩展被下载,或者因为其它的多种多样的原因其它的扩展变得不可用。MEF处理这些多样的场景是依赖我们称作重组的功能来实现的,它可已在最初的组合后改变导入的值。

导入可以通知MEF它通过[Import]使用Allowrecomposition属性来支持重组。看下面的代码片段:

[Export]
public class HttpServerHealthMonitor
{
    [ImportMany(AllowRecomposition=true)]
    public IMessageSender[] Senders { get; set; }
}

这告诉MEF,你的类准备来处理重组,并且,如果IMessageSender实现者可用性改变(一个新的实现者可用或不可用),这个集合将被改变以在catalog中反映此
变化。一旦部件选择了允许重组,无论什么时候在catalog中可用的实现者有改变,或实例被手动地从容器中添加/移除,这些
都将使可重组部件得到通知。

重组的附加说明

  • 当重组发生时,我们将用一个新的实例来替换集合/数组的实例,我们将不会更新已存在的实例。在上面的例子中,如果一个新的IMessageSender实例出现了,Senders将被一个新的数组完全替换。这是为了促进现场安全。
  • 重组几乎对于支持导入的所有类型都有效,像字段,属性和集合,但是它不支持构造器参数。
  • 如果你的类型碰巧实现了IPartImportsSatisfiedNotification接口,无论重组何时发生,导入完成也将会被调用

最后举个例子:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ClassLibrary2;
using System.Timers;

namespace RecompositionExample
{
    class Program
    {
        [ImportMany(AllowRecomposition=true)]
        public IEnumerable<IMessageSender> Senders { get; set; }
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Compose();
            p.Print();
            Console.ReadKey();
        }
        private AggregateCatalog catalog;
        private Timer t;
        void t_Elapsed(object sender, ElapsedEventArgs e)
        {
            catalog.Catalogs.Add(new DirectoryCatalog("Plugins", "*.dll"));
            t.Enabled = false;
            Console.WriteLine("-----------------");
            Print();
        }
        void Compose()
        {
            catalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
            t = new Timer(5000);
            t.Elapsed += t_Elapsed;
            t.Start();
        }
        void Print()
        {
            foreach (var item in Senders)
            {
                item.Send("Hi,MEF");
            }
        }
    }
    [Export(typeof(IMessageSender))]
    class EmailSender : IMessageSender
    {
        public void Send(string msg)
        {
            Console.WriteLine("Email sent:" + msg);
        }
    }
    class TcpSender : IMessageSender
    {
        public void Send(string msg)
        {
            throw new NotImplementedException();
        }
    }

}
原文地址:https://www.cnblogs.com/jellochen/p/3670504.html