array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 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);
        }
    }

}

 

 效果如图:

MEF初体验之四:Imports声明

参数导入

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

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

效果如下:

MEF初体验之四:Imports声明

相关文章: