zoukankan      html  css  js  c++  java
  • MEF初体验之四:Imports声明

    组合部件使用[System.ComponentModel.Composition.ImportAttribute]特性声明导入。与导出类似,也有几种成员支持,即为字段、属性和构造器参数。同样,我们也来看下该特性类的声明:

    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field 
    | AttributeTargets.Property, AllowMultiple=false, Inherited=false)] public class ImportAttribute : Attribute, IAttributedImport { }

    果然,支持这三种成员(这里Parameter而不是GenericParameter),也不支持继承,另外,与[Export]不同的是,在同一个目标上不能应用多次该特性

    属性倒入

    为了向属性导入一个值,用[Import]来声明该属性。这是我们在前面的例子中使用的。例如下面倒入一个IMessageSender的代码片段:

    [Import]
    public IMessageSender MessageSender { get; set; }

    构造函数参数

    你也可以指定构造函数参数导入。这意味着你是将构造函数参数添加各自的导入,而不是将属性添加各自的导入。为了使用它,按照下面的步骤:

    1. 添加一个[System.ComponentModel.Composition.ImportingConstructorAttribute]特性到应该被MEF使用的构造函数上。
    2. 为构造函数参数添加各自的导入

    例如,下面的代码在Program类构造函数上导入一个message sender。

    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;
    
    namespace ImportsDeclaring
    {
        class Program
        {
            static void Main(string[] args)
            {
                Program p = new Program();
                p.Run();
                Console.ReadKey();
            }
            void Run()
            {
                var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
                var container = new CompositionContainer(catalog);
                container.ComposeExportedValue<IMessageSender>(new EmailSender());
                var s = container.GetExportedValue<IService>();
                s.Work();
            }
        }
        [Export(typeof(IService))]
        class SenderService:IService
        {
            private IMessageSender sender;
            [ImportingConstructor]
            public SenderService([Import(AllowDefault = true)]IMessageSender sender)
            {
                this.sender = sender;
            }
    
            void IService.Work()
            {
                if (sender != null)
                    sender.Send("Hi,MEF");
            }
        }
        interface IService
        {
            void Work();
        }
        interface IMessageSender
        {
            void Send(string msg);
        }
        class EmailSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("Email Sent:" + msg);
            }
        }
    
    }

     效果如图:

    参数导入

    在构造函数上定义导出有这么几种不同的方式:

    1. 隐式导入-容器将会默认地使用参数的类型来识别契约。
    2. 显示导入-给参数添加[Import]特性,以此来制定要导入的契约

    例如下面的两种方式等价:

    [ImportingConstructor]
    public
    SenderService(IMessageSender sender) { this.sender = sender; } [ImportingConstructor] public SenderService([Import(typeof(IMessageSender))]IMessageSender sender) { this.sender = sender; }

    字段导入

    MEF也支持直接将值导入到字段。形式上和属性导入很像。但是需要注意的是,私有成员(字段、属性和方法)的导入或导出仅仅支持在中/部分信任应用中,而在完全信任应用的支持上可能会有问题。

    可选导入

    MEF允许你指定一个可选的导入。当你启用它时,如果有可用的导出,这个容器将会提供该导出,并且设置导入为Default(T)。为了利用导入选项,在[Import]上设置AllowDefault=true。在上面我们已经使用了它,作用是当我们未执行container.ComposeExportedValue<IMessageSender>(new EmailSender()),即未给构造函数参数导入值,这时,[Import(AllowDefault=true)]相当于container.ComposeExportedValue<IMessageSender>(null),虽然参数值为null,但是契约匹配仍然生效,而如果AllowDefault=false(默认值),这时,构造器参数导入无法匹配导出,在执行下一行代码var s = container.GetExportedValue<IService>();就会报错。

    导出集合

    除了单个导出之外,你可以使用[ImportMany]来导出集合。这意味着指定的契约的所有实例都将被导入到这个容器。

    MEF部件也支持重组。这意味着当在容器中新的导出可用时,集合会自动更新。

    IPartImportsSatisfiedNotification接口

     在某些场合,当MEF在处理类的实例导入过程时,该类能得到通知,对于该类来说这可能是重要的。如果是这种情况的话,请实现IPartImportsSatisfiedNotification接口,这个接口只有一个方法:OnImportsSatisfied,当所有满足部件的导入都满足时该方法将被调用。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ImportsDeclaring
    {
        class Example
        {
            static void Main(string[] args)
            {
                Example e = new Example();
                Notifier noter = new Notifier();
                var container = new CompositionContainer();
                container.ComposeParts(noter, new EmailSender(), new TcpSender(), new PhoneSender());
                noter.Notify("Hi,MEF");
                Console.WriteLine("-----------------");
                noter.MessageSender.Send("Hi,MEF");
                Console.ReadKey();
            }
        }
        class Notifier:IPartImportsSatisfiedNotification
        {
            [ImportMany]
            public IEnumerable<IMessageSender> Senders { get; set; }
            [Import("PhoneSender")]
            public IMessageSender MessageSender { get; set; }
            public void Notify(string msg)
            {
                foreach (var item in Senders)
                {
                    item.Send(msg);
                }
            }
    
            public void OnImportsSatisfied()
            {
                Console.WriteLine("all imports that could be satisfied have been satisfied");
            }
        }
        [Export(typeof(IMessageSender))]
        class EmailSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("Email Sent:" + msg);
            }
        }
        [Export(typeof(IMessageSender))]
        class TcpSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("TCP Sent:" + msg);
            }
        }
        [Export("PhoneSender", typeof(IMessageSender))]
        class PhoneSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("Phone Sent:" + msg);
            }
        }
    }

    效果如下:

  • 相关阅读:
    sql优化
    mysql_存储过程_后一行减去前一行
    python基础笔记
    atom使用markdown
    tensorboard遇到的坑
    WordPaster-Firefox浏览器控件安装方法
    WordPaster.exe安装教程
    Web大文件上传控件-bug修复-Xproer.HttpUploader6
    Web大文件下载控件更新-Xproer.HttpDownloader
    Web大文件上传控件-asp.net-bug修复-Xproer.HttpUploader6.2
  • 原文地址:https://www.cnblogs.com/jellochen/p/3662268.html
Copyright © 2011-2022 走看看