`
jiasongmao
  • 浏览: 671144 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用

阅读更多

本文章非原创,转载自:

作      者:Beniao

文章出处:http://beniao.cnblogs.com/   或  http://www.cnblogs.com/

 

按照MEF的约定,任何一个类或者是接口的实现都可以通过[System.ComponentModel.Composition.Export] 属性将其他定义组合部件(Composable Parts),在任何需要导入组合部件的地方都可以通过在特定的组合部件对象属性上使用 [System.ComponentModel.Composition.Import ]实现部件的组合,两者之间通过契约(Contracts)进行通信,实际上这一步可以简单的理解为“依赖注入”,本质上就是对象的实例初始化过程。

 

  我个人理解,凡是通过MEF的[ExportAttribute]标注的对象都可以理解为一个可进行组合的部件,包括对象和对象的属性、字段、方法、事件等;且该对象可以通过[ImportAttribute]进行导入。如下示例代码:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
public class StringProvider
{
    /// <summary>
    /// 定义导出部件--契约为“Message”
    /// </summary>
    [Export("Message")]
    public string Output
    {
        get { return "Hello World"; }
    }
}

public class Client
{
    /// <summary>
    /// 导入指定契约的部件
    /// </summary>
    [Import("Message")]
    public string Input { get; set; }

    public void Print()
    {
        Console.WriteLine(Input);
    }
}
 

 

  所谓的契约也就是一种约定,或者叫做一种规则。如上代码中就使用到了契约,在对象StringProvider中就定义了一个导出部件属性 (Output),并为其指定了通信契约为“Message”。这里的“Message”就是一种约定,既约定为在需要使用到这个属性的地方,都可以通过 [ImportAttribute]使用契约(Message)进行部件的导入。

 

  接下来结合《Silverlight中使用CompositionInitializer宿主MEF 》一文中使用的日志记录的应用实例为基础来看看关于契约(Contracts)在较为复杂的部件中的的具体使用方法。假设定义了如下的接口与部件实现代码:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
public interface ILogger
{
    void WriteLog(string message);
}
    
[Export(typeof(ILogger))]
public class TXTLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("TXTLogger>>>>>" + message);
    }
}

[Export(typeof(ILogger))]
public class DBLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("DBLogger>>>>>" + message);
    }
}
 

 

  对于熟悉面向对象设计方法的人一眼就能明白,上面代码演示了一个接口具有多个实现的场景,仔细观察会发现在每个实现类上面都添加了 [ExportAttribute]将其标注为导出部件,并为其添加了通信契约,而且两个实现类的通信契约都是使用的接口(ILogger)的类型参数。

  这里需要注意的是在进行导入的时候如果辨别到底是使用的哪一个实现呢?在MEF中提供了一个专门用于导入多个实现的特性 [System.ComponentModel.Composition.ImportManyAttribute],如上的日志实现示例就可以通过如下 的方式实现多部件导入。

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
[ImportMany]
public IEnumerable<ILogger> Loggers { get; set; }
 

 

     

 

   ImportManyAttribute特性可以将实现接口的所有实现全部组合起来。下面为使用[ImportMany]的完整示例代码:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
namespace MEFTraining.CPC
{
    public partial class MainPage : UserControl
    {
        [ImportMany]
        public IEnumerable<ILogger> Loggers { get; set; }

        public MainPage()
        {
            InitializeComponent();

            CompositionInitializer.SatisfyImports(this);
            if (Loggers == null)
            {
                foreach (var logger in Loggers)
                {
                    logger.WriteLog("Hello World");
                }
            }
        }
    }

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

    [Export(typeof(ILogger))]
    public class TXTLogger : ILogger
    {
        public void WriteLog(string message)
        {
            MessageBox.Show("TXTLogger>>>>>" + message);
        }
    }

    [Export(typeof(ILogger))]
    public class DBLogger : ILogger
    {
        public void WriteLog(string message)
        {
            MessageBox.Show("DBLogger>>>>>" + message);
        }
    }
}
 

 

   上面介绍了如何在相同的契约下获取所有导出部件的实例,在某种情况下或许我们就只直接指导需要使用那一种那个实现方式,那么是否可以通过直接 指定一个“契约名”就可以从多个实现中获取到指定的组合部件呢?答案是肯定的,接下来先看看在MEF中中对ExportAttribute和 ImportAttribute的定义,源代码如下:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
public class ExportAttribute : Attribute
{
    public ExportAttribute() : this((string)null, (Type)null){}
    public ExportAttribute(Type contractType) : this((string)null, contractType){}
    public ExportAttribute(string contractName) : this(contractName, (Type)null) { }
    public ExportAttribute(string contractName, Type contractType)
    {
        this.ContractName = contractName;
        this.ContractType = contractType;
    }

    public string ContractName { get; private set; }
    public Type ContractType { get; private set; }
}
 

 

  ImportAttribute同ExportAttribute一样提供了相同的重载构造函数,在将一个对象进行导出部件处理的时候可以直接通过ImportAttribute的属性给对象指定一个契约名,如本篇前面的日志组件的实现就可以修改为如下代码格式。

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
public interface ILogger
{
    void WriteLog(string message);
}
    
[Export("TXT", typeof(ILogger))]
public class TXTLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("TXTLogger>>>>>" + message);
    }
}

[Export("DB", typeof(ILogger))]
public class DBLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("DBLogger>>>>>" + message);
    }
}
 

 

  通过为不同的导出部件指定了特定的契约名称,那么在装配部件的时候就可以通过契约名进行指定部件的装配并组合部件,为了方便调用可以提供一个服务类,将不同的实现通过不同的契约名装载组合起来以对系统提供一个统一的调用入口。以下为完整的示例代码:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
public partial class MainPage : UserControl
{
    /// <summary>
    /// 导入日志服务对象
    /// </summary>
    [Import]
    public LogService Service { get; set; }

    public MainPage()
    {
        InitializeComponent();

        CompositionInitializer.SatisfyImports(this);

        Service.DBLogger.WriteLog("Hello MEF");
        Service.TXTLogger.WriteLog("Hello MEF");
    }
}

/// <summary>
/// 聚合不同的日志记录部件,通过MEF进行组合
/// </summary>
[Export]
public class LogService
{
    /// <summary>
    /// 根据契约名进行部件的装配
    /// </summary>
    [Import("TXT")]
    public ILogger TXTLogger { get; set; }

    [Import("DB")]
    public ILogger DBLogger { get; set; }
}

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

[Export("TXT", typeof(ILogger))]
public class TXTLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("TXTLogger>>>>>" + message);
    }
}

[Export("DB", typeof(ILogger))]
public class DBLogger : ILogger
{
    public void WriteLog(string message)
    {
        MessageBox.Show("DBLogger>>>>>" + message);
    }
}

 
分享到:
评论

相关推荐

    Silverlight MEF 演示源代码

    MEF(Managed Extensibility Framework)是微软提供的一种用于构建可扩展应用程序的框架,它在Silverlight中扮演着重要角色,尤其是在大型复杂项目中,帮助开发者实现模块化和插件化。 在"Silverlight MEF 演示源...

    MEF简单应用

    在本篇中,我们将探讨MEF的基本概念、如何导入和导出部件,以及如何在控制台应用程序中实现一个简单的MEF应用。 **MEF的核心概念** 1. **部件(Parts)**:在MEF中,任何可以被导入和导出的对象都被称为部件。部件...

    Mef_MEFwinForm_

    1. **MEF基础**:了解MEF的基本概念,如Composable Parts(可组合部分)、Export(导出)和Import(导入)特性,以及如何定义和使用它们。 2. **插件架构**:理解如何设计和实现一个插件架构,包括定义插件接口,...

    MEF Console Example

    1. **Composable Parts(可组合部件)**:这些是定义了服务或功能的类,它们通过导入(Import)和导出(Export)特性标记,表明它们对其他组件的依赖以及自身可以提供的服务。 2. **Catalogs(目录)**:MEF使用...

    MEF组件式开发,模块化开发

    MEF允许开发者将应用程序划分为独立的、可替换的组件,这些组件可以动态地发现并集成到系统中,从而实现了模块化的开发模式。 ### 1. MEF基础概念 - **部件(Part)**:在MEF中,一个部件代表了一个可插拔的组件,...

    Managed Extensibility Framework(MEF)

    1. **部件(Parts)**:MEF中的基本构建块,可以是任何.NET类型的实例,如类、接口或其他自定义类型。这些部件可以包含导出(Exports)和导入(Imports)。 2. **导出(Exports)**:部件提供给其他部件使用的功能...

    WPF中MEF的应用,简单实例

    在Windows Presentation Foundation(WPF)开发中,Microsoft Managed Extensibility Framework(MEF)是一种强大的工具,用于实现应用程序的模块化和插件化。MEF提供了一种灵活的方式,使得组件之间可以互相发现和...

    MEF框架整理学习内容

    1. **部件(Parts)与组合(Composition)** - **部件**是指通过MEF进行管理的对象,可以是一个类、接口或是任何可被扩展的部分。 - **组合**指的是将这些部件组织在一起的过程。MEF通过组合容器...

    MEF框架源代码 MEF框架源代码 MEF框架源代码

    6. **部分类(Part)**:在MEF中,组件通常被称为“部分”,因为它们可以是整个应用程序的一部分,每个部分都可能独立地被替换或扩展。 7. **目录(Catalog)**:目录是包含组件定义的集合,它可以是基于文件系统、...

    MEF 注入框架入门导引 ppt

    - **MEF(Managed Extensibility Framework)**:是.NET Framework中的一个新库,旨在提高应用程序和组件的重用能力。通过使用MEF,.NET应用能够从静态编译转变为动态组合。 - **软件开发与维护的挑战**: - 原始...

    MEFDemo简单入门示例

    4. **Composable Parts Container(可组合部件容器)**:这是MEF的核心组件,负责管理所有部件,发现它们的导出和导入,并进行匹配和连接,以满足部件间的依赖关系。 5. **Catalog(目录)**:目录是部件的集合,...

    MEF简单模型

    1. **部件(Parts)**:在MEF中,部件是指实现特定接口或具有特定属性的类。它们可以是任何.NET类型,如类、接口或委托。部件是MEF的基础构建块,可以作为服务提供者或消费者。 2. **导入(Imports)**:部件可能有...

    MEF 结合 MVVMLight

    **MEF(Managed Extensibility Framework)与MVVMLight结合使用是现代Windows应用程序开发中的一个常见实践,尤其在WPF和Silverlight项目中。MEF是一个用于构建可扩展应用程序的.NET框架,而MVVMLight则是一个轻量级...

    WPF下使用MEF导入带参数构造函数的用户控件

    在Windows Presentation Foundation (WPF) 应用程序开发中,我们常常会遇到需要动态加载、组合组件的情况。Managed Extensibility Framework (MEF) 是一个用于构建可扩展应用程序的库,它提供了强大的依赖注入...

    C#MEF简单例子

    2. 灵活性:MEF 提供了一种灵活的方式来组合不同的组件,以创建一个功能强大且灵活的应用程序。 3. 松耦合:MEF 使得组件之间的耦合度降低,提高了系统的可维护性和可扩展性。 结论 MEF 是一个功能强大且灵活的...

    MEF学习Demo

    在.NET框架中,Managed Extensibility Framework(MEF)是一个强大的组件组合和插件框架,它允许开发者构建可扩展的应用程序。MEF的主要目标是简化软件的组件化和模块化,使得第三方开发者可以轻松地为程序添加新...

    Silverlight Mef Demo

    总结来说,"Silverlight Mef Demo"是一个绝佳的学习资源,它不仅展示了Silverlight的基本应用,还深入探讨了MEF在构建可扩展性应用中的实践,对于想要提升自己在Silverlight和MEF方面技能的开发者来说,这是一个不容...

    Mef实现的简单例子

    **MEF(Managed Extensibility Framework)**是.NET框架中的一部分,主要用于构建可扩展的应用程序。这个框架允许开发者轻松地引入外部组件,并在运行时发现和组合这些组件,以实现高度灵活和模块化的应用程序设计。...

    扩展性MEF.rar111

    1. **部件(Parts)**: 在MEF中,任何可以被导入和导出的类或对象都被称为部件。部件可以定义自己的依赖,通过属性或者构造函数参数进行导入。 2. **导出(Exports)**: 部件通过使用`[Export]`特性标记成员(如类...

    mef与wcf整合

    - 开发者可以创建独立的插件,这些插件包含WCF服务的实现,然后通过MEF将它们插入到主应用程序中。这种方式使得系统更易于扩展和维护。 8. **异常处理和生命周期管理**: - MEF提供了一种统一的方式来处理服务...

Global site tag (gtag.js) - Google Analytics