zoukankan      html  css  js  c++  java
  • MEF简单示例

    原文地址: http://www.cnblogs.com/xiaokang088/archive/2012/02/21/2361631.html

     

    MEF 的精髓在于插件式开发,方便扩展。

    例如,应用程序的日志输出到文本,后来想改为输出到数据库,按照传统的办法,需要替换项目,删除原有的引用,增加新的引用;如果使用MEF,直接用新的dll替换原来的dll,即可搞定,这就是MEF的魅力。

    下面就用简单的例子来实现上述的需求。

    1. 建立一个解决方案,然后增加如下的几个项目

     

    DBlog 输出日志到数据库的实现

    TextLog 输出日志到文本的实现

    ILog 输出日志的接口,调用方和实现者的中间桥梁

    MEFConsoleHost 控制台应用程序,模拟实用场合

    MEFWPFHost WPF 应用程序,模拟实用场合

     

    2. 先定义接口ILog,非常简单,就一个方法

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ILog
    {
        public interface ILogService
        {
            void Log(string content);
        }
    }

     

    3. 输出到文本的实现TextLog

      

    首先添加引用:引用刚才添加的接口Ilog 和System.ComponentModel.Composition

    然后增加类TextLogService.cs,继承接口,并实现方法。

    注意 类和方法都Public。

    最后定义导出[Export(typeof(ILog.ILogService))]

    这个是最主要的,和普通的类库区别也在这里 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using System.ComponentModel.Composition;
    
    namespace TextLog
    {
        [Export(typeof(ILog.ILogService))]
        public class TextLogService : ILog.ILogService
        {
            public void Log(string content)
            {
                Console.WriteLine("TextLog:" + content);
    
                System.Diagnostics.TextWriterTraceListener TraceListener = new System.Diagnostics.TextWriterTraceListener(@"d:/debug.txt");
                System.Diagnostics.Debug.Listeners.Add(TraceListener);
                System.Diagnostics.Debug.Write(System.DateTime.Now.ToString()+"   "); 
                Debug.Write("TextLog:" + content);
                Debug.WriteLine("~~");
                TraceListener.Flush();
            }
        }
    }

      

    4. 输出到数据库的实现DBLog,实现方法同上例,输出日志的时候区分一下。 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using System.ComponentModel.Composition;
    
    namespace DBLog
    {
        [Export(typeof(ILog.ILogService))]
        public class DBLogService: ILog.ILogService
        {
            public void Log(string content)
            {
                Console.WriteLine("DBLog:" + content);
    
                System.Diagnostics.TextWriterTraceListener TraceListener = new System.Diagnostics.TextWriterTraceListener(@"d:/debug.txt");
                System.Diagnostics.Debug.Listeners.Add(TraceListener);
                System.Diagnostics.Debug.Write(System.DateTime.Now.ToString()+"   "); 
                Debug.Write("DBLog:" + content);
                Debug.WriteLine("");
                TraceListener.Flush();
            }
        }
    }

    5. 调用方MEFConsoleHost, 这个也需要增加两个引用,

    ILog 和System.ComponentModel.Composition

    主程序代码如下:  

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    
    namespace MEFConsoleHost
    {
        class Program
        {
            [Import(typeof(ILog.ILogService))]
            public ILog.ILogService CurrentLogService { get; set; }
    
            static void Main(string[] args)
            {
                Program pro = new Program();
                pro.run();
            }
    
            private void run()
            {
                //var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,"DbLog.dll");
                var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory, "TextLog.dll");
    
                var container = new CompositionContainer(catalog);
                container.ComposeParts(this);
    
                CurrentLogService.Log("*MEF Log Test Pass*");
                Console.Read();
            }
        }
    }

     注意两个地方

    a. 导入声明 

    [Import(typeof(ILogService))]
    public ILogService CurrentLogService { get; set; }

    用接口来定义实例,然后增加导入声明,和导出的相互对应

    b. 建立Catalog和Container

    var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory, "TextLog.dll");
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);


    6. 把所有项目的输出都指定到同一个目录,也就说让dll和exe在同一目录,运行控制台程序,输出

    TextLog: MEF Log Test Pass

     

    7.如果我们要输出到数据库,把上面的catalog那一句改成

    var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,"DBLog.dll");

    如果不想这么麻烦,这个目录里面只放DBLog.dll 或者TextLog.dll ,然后把上面那句改为:

    var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);

    照样可以用。

    如果两个都在,还这么搞,那不行的,因为就定义了一个实例,同目录有两个dll。

  • 相关阅读:
    [Cisco答疑]思科产品常见问题问答大汇总
    英语名人名言
    [配置实例]三层交换机组播配置实例
    利用VLAN技术组建三层线速校园网
    神州数码交换机配置基本命令
    SQL命令大全中英文对照
    SQL通用防注入系统3.1 最终纪念版
    带关闭按钮的浮动窗口
    Document方法对比
    HTML元素参考手册
  • 原文地址:https://www.cnblogs.com/gsk99/p/4940176.html
Copyright © 2011-2022 走看看