zoukankan      html  css  js  c++  java
  • MEF学习系列笔记系列(1)

                 最近,年底项目开始有点空闲,跟我们对接接口的那边正在开发,而我们这边开发完毕,但是对方接口不稳定而且很不成熟,所以暂时停止对接,等稳定再进行对接,本日在对接接口方面经验比较足,所以敢于拿出时间去学习新的知识,觉得MEF以前没怎么接触,最近想提升一下,所以就写呢这篇文章,供大家学习,由于这方面经验有限,有什么不足,望大家指出,我的Email为:wangyonghua_net@126.com.

               MEF参考资料主要来源:   

                王春明- http://www.cnblogs.com/wangchunming/archive/2012/04/23/2467128.html,

               一个人在北京- http://www.cnblogs.com/content/archive/2013/05/31/3111156.html

               以前觉得自己懂就可以啦,没有做像样的总结,给大家分享,现在我觉得写博客也要认真的对待,把实际遇到的问题,自己的理解分享给大家,望与大家交流,相互学习.

              应用程序里托管MEF

               应用程序里托管MEF包括创建一个CompositionContainer实例,添加组成部件,包括宿主本身,然后组合。

              下面是组合的步骤:

    创建一个宿主类,下面的例子里我们使用控制台应用程序,所以宿主是Program类。

    添加System.ComponentModel.Composition的引用;

    在头部添加using System.ComponentModel.Composition;

    添加一个Compose()方法,用来创建一个container实例,并跟宿主组合;

    添加一个Run()方法,用来执行Compose();

    在Main()里实例化宿主类。

    注意:对于ASP.NET和WPF应用程序,宿主类在运行时就已经实例化,所以这个步骤没有必要。

      using System.ComponentModel.Composition;
      using System.ComponentModel.Composition.Hosting;
      using System.Reflection;
      using System;
    
      public class Program
      {
        public static void Main(string[] args)
        {
           Program p = new Program();
           p.Run();
        }
        public void Run()
        {
           Compose();
        }
        private void Compose()
        {
           var container = new CompositionContainer();
           container.ComposeParts(this);
        }
      }
    定义一个或多个导出(Export)用于给宿主导入(Import)。下面的代码,我们会定义一个IMessageSender接口,我们还会定义一个EmailSender组合部件,用来导出一个IMessageSender,这得通过声明 [System.ComponentModel.Composition.Export] 属性来实现:

    public interface IMessageSender
      {
        void Send(string message);
      }
    
      [Export(typeof(IMessageSender))]
      public class EmailSender : IMessageSender
      {
        public void Send(string message)
        {
          Console.WriteLine(message);
        }
      }
    通过使用[System.ComponentModel.Composition.Import]修饰的属性,使每个导入将特性添加到宿主类。下面的例子是一个IMessageSender的导入将特性添加给Program类:

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

    给容器添加部件。在MEF有几个方法可以做到这个。一个方法是直接添加目前的组成部件实例,另一个更常用的方法是通过使用目录,这个我们在下面的章节会提到.

    直接添加部件到容器
    在Compose()方法里通过重载方法ComposeParts()手动添加每个组成部件。下面的例子里一个EmailSender的实例和当前要导入的Program实例一起添加到容器。

      private void Compose()
      {
        var container = new CompositionContainer();
        container.ComposeParts(this, new EmailSender());
      }

    用数据集目录(AssemblyCatalog)添加到容器(container)
    通过使用这个目录,container句柄会自动添加部件,而不是显式的添加。为了实现这个,在Compose()里创建一个目录catalog。然后从目录创建一个解析器,把它传给container的构造函。
    下面的例子是一个用正在执行的程序集创建的AssemblyCatalog传进构造函数。我们没有添加EmailSender实例因为它会在当前程序集的目录被发现。
    private void Compose()
      {
        var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
      }

    Assembly.GetExecutingAssembly()Gets the assembly that contains the code that is currently executing.
    经过上面的步骤之后,代码应该是这样:

    using System.ComponentModel.Composition;
      using System.ComponentModel.Composition.Hosting;
      using System.Reflection;
      using System;
    
      public class Program
      {
        [Import]
        public IMessageSender MessageSender { get; set; }
    
        public static void Main(string[] args)
        {
          Program p = new Program();
          p.Run();
        }
    
        public void Run()
        {
          Compose();
          MessageSender.Send("Message Sent");
        }
    
        private void Compose()
        {
          AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
          var container = new CompositionContainer(catalog);
          container.ComposeParts(this);
        }
      }
    
      public interface IMessageSender
      {
        void Send(string message);
      }
    
      [Export(typeof(IMessageSender))]
      public class EmailSender : IMessageSender
      {
        public void Send(string message)
        {
          Console.WriteLine(message);
        }
      }

    执行上面的代码,应用程序会用它的IMessageSender导入来组装,之后Send()会被执行,结果会输出“Message Sent”



    同时我也做呢另外一个控制台项目,宿主代码代码如下:

     class Program
        {
            [ImportMany]
            public ILogger[] Loggers { get; set; }
    
            /// <summary>
            ///下面的代码说明如何启动在MEF组成过程。
            ///下面的步骤用于静态构造函数: 
            ///创建目录 (告诉MEF寻找部件 ) 
            ///创建容器 (主机),并交给目录 。 
            ///容器调用Compose方法。 
            ///最后一步是从容器中获得logger
            /// </summary>
            /// <param name="args"></param>
            static void Main(string[] args)
            {
                var p = new Program();
                var assemblyCatalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
                var container = new CompositionContainer(assemblyCatalog);
                container.ComposeParts(p);
    
                foreach (var logger in p.Loggers)
                {
                    logger.Write("写日志");
                }
                Console.Read();
            }
        }
    部件与契约:

    public interface ILogger
        {
            void Write(string message);
        }

     /// <summary>
        /// 下面的代码是使用导出属性的部分装饰
        ///要求为ILogger契约。
        /// </summary>
        [Export(typeof(ILogger))]
        public class ConsoleLogger : ILogger
        {
            void ILogger.Write(string message)
            {
                Console.WriteLine(message);
            }
        }
    
        [Export(typeof(ILogger))]
        public class DebugLogger : ILogger
        {
            void ILogger.Write(string message)
            {
                Debug.WriteLine(message);
            }
        }
    
        [Export(typeof(ILogger))]
        public class EventLogLogger : ILogger
        {
            void ILogger.Write(string message)
            {
                EventLog.WriteEntry("MEFSample", message);
            }
        }

    结果运行如下:





  • 相关阅读:
    PIE-SDK For C++栅格数据的金字塔创建
    PIE-SDK For C++栅格数据集的读写
    PIE-SDK For C++栅格数据集的读取
    PIE-SDK For C++内存栅格数据的创建
    【系列文章】数据结构与算法——图
    大小端模式
    几种常见的排序方法(C语言实现)
    WPF——数据绑定(二)绑定方法—绑定本地对象
    WPF——数据绑定(一)什么是数据绑定
    WPF多窗口传参解决方案
  • 原文地址:https://www.cnblogs.com/wangyhua/p/4050545.html
Copyright © 2011-2022 走看看