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

}
复制代码
posted @   jello chen  阅读(459)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报

点击右上角即可分享
微信分享提示