• MEF只导出类的成员


    MEF只导出类的成员

    通过前面两篇文章的介绍,相信各位会明白MEF中有不少实用价值。上一文中我们也讨论了导入与导出,对于导出导入,今天我们再深入一点点,嗯,只是深入一点点而已,不会很难的,请大家务必放心,如果大家觉得看文章枯燥,不妨一边喝牛奶一边阅读。

     

    上一文中我们都是把整个类型(整个类)进行导出,不过有时候,我们可能会考虑只导出类的某些成员,比如某个属性或某个字段等。

     

    我们还是少说理论,免得大家喝不下牛奶,还是直接上菜吧。为了便于测试,以下示例把组件都写在当前程序集中,也就是在同一个项目,然后用AssemblyCatalog来查找。

     

    首先,定义一个公共接口IWork。

     

     

    然后分别用两个类来实现该接口。

     

     

     

     

    接着,我们再定义一个总类,包含两个属性,分别返回FirstWork类和SecondWork类的实例。

     

     

    ExportAttribute特性只附加在WorkFirst和WorkSecond两个属性上,Works类只导出这两个属性。

     

    随后,我们组装并调用这些导出部件。

     

     

     

    然后我们运行一下示例,就可以得到如下图所示的结果:

     

     

    很多人学习编程很喜欢直接Ctrl + C别人的代码,这是一种相当不好的学习方法,所以我把代码都弄成截图了,哈哈。

     

    我事前在导入字段声明时用了Lazy<T>,但发现不能创建对象,可能的原因是我们导出的是类的一部分,内部运行时在组装部件时需要Works类进行实例化,因为如果Works对象不实例化的话,就导不出WorkFirst和WorkSecond属性了。也许是这个原因导致的吧。

     

    这时候大家可能会想,如果我在Works类中定义一个方法,我想导出这个方法怎么办?

     

    既然想到了还等什么,马上试试就知道了,我们把Works类的代码改一下,导出一个ViewWork方法。

     

     

    协定类型为什么使用Func<TResult>呢?为什么,大家好好思考一下,用什么方式来表示方法的签名与形式最形象?想想吧。

     

    接着我们在Program类中导入这个方法。

     

     

    导入的协定名与协定类型一定要与导出匹配,否则无法导入。这就好比你的言行要匹配一样,否则妹子不会理你。

     

    在完成组装的代码后面,我们测试调用导入的方法。

     

     

    然后运行一下,看看有没有结果。

     

     

    不过,最后,还是把完整的代码贴一下。

     

    using System;

     

    using System.Collections.Generic;

     

    using System.Linq;

     

    using System.Text;

     

    using System.Threading.Tasks;

     

    using System.ComponentModel.Composition;

     

    using System.ComponentModel.Composition.Hosting;

     

    using System.Reflection;

     

     

    namespace MefApp

     

    {

     

    // 作为公共接口

     

    public interface IWork

     

    {

     

    void DoSome();

     

    string WName { get; }

     

    }

     

     

    // 第一个实现公共接口的类

     

    public class FirstWork : IWork

     

    {

     

    public void DoSome()

     

    {

     

    Console.WriteLine("工序一执行。");

     

    }

     

     

    public string WName

     

    {

     

    get { return "工序一"; }

     

    }

     

    }

     

     

    // 第二个实现公共接口的类

     

    public class SecondWork : IWork

     

    {

     

     

    public void DoSome()

     

    {

     

    Console.WriteLine("工序二执行。");

     

    }

     

     

    public string WName

     

    {

     

    get { return "工序二"; }

     

    }

     

    }

     

     

    // 只对成员进行导出的类

     

    public class Works

     

    {

     

    FirstWork fw;

     

    SecondWork sw;

     

     

    public Works()

     

    {

     

    // 初始化

     

    fw = new FirstWork();

     

    sw = new SecondWork();

     

    }

     

     

    // 该属性被导出

     

    [Export("work 1"typeof(IWork))]

     

    public IWork WorkFirst { get {

     

    return fw;

     

    } }

     

     

    // 该属性被导出

     

    [Export("work 2"typeof(IWork))]

     

    public IWork WorkSecond

     

    {

     

    get { return sw; }

     

    }

     

     

    // 导出方法

     

    [Export("view work"typeof(Func<string>))]

     

    public string ViewWork()

     

    {

     

    return "本生产线国际一流,由3172个工作单元组成,73265道工序。";

     

    }

     

    }

     

     

    class Program

     

    {

     

    // 导入

     

    [Import("work 1"typeof(IWork))]

     

    public IWork TheImportFirstWork;

     

     

    // 导入

     

    [Import("work 2"typeof(IWork))]

     

    public IWork TheImportSecondWork;

     

     

    // 导入

     

    [Import("view work"typeof(Func<string>))]

     

    public Func<string> TheImportViewWorkMethod;

     

     

    static void Main(string[] args)

     

    {

     

    // 从当前程序集中发现组件

     

    AssemblyCatalog cat = new AssemblyCatalog(typeof(Program).Assembly);

     

    Program p = new Program();

     

    CompositionContainer container = new CompositionContainer(cat);

     

    container.SatisfyImportsOnce(p);//给合

     

     

    // 调用测试

     

    if (p.TheImportFirstWork!=null)

     

    {

     

    Console.Write("类型名:{0} Name:{1} 调用结果:",

     

    p.TheImportFirstWork.GetType().Name,

     

    p.TheImportFirstWork.WName);

     

    p.TheImportFirstWork.DoSome();

     

    }

     

    if (p.TheImportSecondWork != null)

     

    {

     

    Console.Write("类型名:{0} Name:{1} 调用结果:",

     

    p.TheImportSecondWork.GetType().Name,

     

    p.TheImportSecondWork.WName);

     

    p.TheImportSecondWork.DoSome();

     

    }

     

    if (p.TheImportViewWorkMethod != null)

     

    {

     

    Console.WriteLine(p.TheImportViewWorkMethod());

     

    }

     

     

    // 释容器以及其创建的实例

     

    container.Dispose();

     

    Console.Read();

     

    }

     

    }

     

    }

     

     

     

     

     

     
    标签: MEF

  • 相关阅读:
    Java线程基础(二)
    Java线程基础(一)
    泛型集合List的详细用法
    Java中日期格式(String、Date、Calendar)的相互转换
    重写Java中包装类的方法
    Java的集合框架(第一次小结)
    node.js 调用mysql 数据库
    win10 系统解决mysql中文乱码问题
    vue-echarts图表
    文件上传的几个例子
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3289540.html
Copyright © 2020-2023  润新知