MEF中使用导出与导入,实质上就是对一个对象的实例化的过程,通过MEF的特性降低了对象的直接依赖,从而让系统的设计达到一种高灵活、高扩展性的效果。在具体的设计开发中,存在着某些对象是不需要在系统运行或者的附属对象初始化的时候进行实例化的,仅仅只需要在需要使用到他的时候才会进行实例化,从系统的上来说这也是提高系统性能的一种可行的实现方式,这种方式就可以理解为对象的迟延初始化,或者叫迟延加载。MEF也对此使用场景提供了完善的实现机制,下面来看看在MEF中的迟延初始化是如何使用的。

namespace MEFTraining.LzayImports
{
    public interface ILogger
    {
        void WriteLog(string message);
    }     [Export(typeof(ILogger))]
    public class DBLogger : ILogger
    {
        public void WriteLog(string message)
        {
            MessageBox.Show(message);
        }
    }
}

  通过使用前几篇博文中使用的日志组件为例,在日志记录的具体实现对象上进行对象的导出[Export]配置。如果是使用传统的方式进行部件的导入则如下代码块所示:

[Import(typeof(ILogger))]
public ILogger Logger { get; set; }

  如果需要进行迟延(Lazy)加载,MEF专门提供了用于迟延加载的方式,既使用Lazy类来完成迟延加载,然后通过其他属性Value获取到所加载到的对象。详细的使用如下代码块:

public partial class MainPage : UserControl
{
    //传统加载
    [Import(typeof(ILogger))]
    public ILogger Logger { get; set; }
    
    //迟延加载
    [Import]
    public Lazy<ILogger> Service;     public MainPage()
    {
        InitializeComponent();         CompositionInitializer.SatisfyImports(this);         Logger.WriteLog("日志内容");         Service.Value.WriteLog("日志内容");
    }
}

  通过调试输出可以得到使用迟延导入的对象的详细信息,下面是通过在命令窗口中输出的Service和Service.Value的详细信息。

Service
ThreadSafetyMode=PublicationOnly, IsValueCreated=true, IsValueFaulted=false, Value={MEFTraining.LzayImports.DBLogger}
    IsValueCreated: true
Service.Value
{MEFTraining.LzayImports.DBLogger}
    [MEFTraining.LzayImports.DBLogger]: {MEFTraining.LzayImports.DBLogger}

  迟延加载还支持元数据的导出和导入,主要使用[MetadataAttribute]特性实现,实际开发中可以进行自定义元数据结构,这里以一个空的元数据接口进行元数据的导入应用演示。

public interface IMetadata
{
      
}

  在导出部件中就可以使用元数据特性进行声明,如下简单的应用。

[MetadataAttribute]
[Export(typeof(Users))]
public class Users
{
    public string UserName = "张三";
}

  元数据的导入应用如下代码块所示:

public partial class MetadataControl : UserControl
{
    [Import(typeof(Users))]
    public Lazy<Users,IMetadata> Users { get; set; }     public MetadataControl()
    {
        InitializeComponent();         //宿主MEF托管扩展容器
        CompositionInitializer.SatisfyImports(this);         MessageBox.Show(Users.Value.UserName);
    }
}

  对于的调试输出为下面代码块所示:

Users
ThreadSafetyMode=PublicationOnly, IsValueCreated=true, IsValueFaulted=false, Value={MEFTraining.LzayImports.Users}
    base {System.Lazy<MEFTraining.LzayImports.Users>}: ThreadSafetyMode=PublicationOnly, IsValueCreated=true, IsValueFaulted=false, Value={MEFTraining.LzayImports.Users}
    Metadata: {_proxy_MEFTraining.LzayImports.IMetadata_0174a468-9771-4271-a37e-9a4a83eca6bd}

  MEF中也提供了专门用于元数据导入、导出的特性[ExportMetadata],使用ExportMetadata基本可以满足大部分元数据的导出、导入支持。通过修改上面的示例来实现自定义元数据结构的导入、导出应用演示。

public interface IMetadata
{
    string Name { get; }
} [ExportMetadata("Name","李四")]
[Export(typeof(Users))]
public class Users
{
    public string UserName = "张三";
}

  上面的示例代码演示了通过元数据导出属性名为“Name”,其值为“李四”的元数据信息,并且还定义了一个用于承载元数据结构的结构,接下来就可以通过迟延加载导入,进行元数据的获取了。

  下图为允许调试中的截图,可以很清楚的看到,在进行迟延导入的时候已经将导出部件中的元数据信息成功的导入到了当前对象实例属性中。

    

  下面是完整的元数据应用实例代码。

 
namespace MEFTraining.LzayImports
{
    public partial class MetadataControl : UserControl
    {
        [Import(typeof(Users))]
        public Lazy<Users,IMetadata> Users { get; set; }         public MetadataControl()
        {
            InitializeComponent();             //宿主MEF托管扩展容器
            CompositionInitializer.SatisfyImports(this);             MessageBox.Show(Users.Value.UserName);
        }
    }     public interface IMetadata
    {
        string Name { get; }
    }     [ExportMetadata("Name","李四")]
    [Export(typeof(Users))]
    public class Users
    {
        public string UserName = "张三";
    }
}

  除此之外,迟延加载也是支持弱类型的元数据类型的,也可以对元数据进行过滤,这里就不做详细的介绍,有兴趣的朋友可以自己去研究研究。

【转】MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)的更多相关文章

  1. 《MEF程序设计指南》博文汇总

    <MEF程序设计指南>博文汇总 在MEF之前,人们已经提出了许多依赖注入框架来解决应用的扩展性问题,比如OSGI 实现以Spring 等等.在 Microsoft 的平台上,.NET Fr ...

  2. [zhuan]《MEF程序设计指南》博文汇总

    http://www.cnblogs.com/beniao/archive/2010/08/11/1797537.html 在MEF之前,人们已经提出了许多依赖注入框架来解决应用的扩展性问题,比如OS ...

  3. [转]《MEF程序设计指南》博文汇总

    在MEF之前,人们已经提出了许多依赖注入框架来解决应用的扩展性问题,比如OSGI 实现以Spring 等等.在 Microsoft 的平台上,.NET Framework 自身内部包含组件模型和 Sy ...

  4. [转]MEF程序设计指南

    <MEF程序设计指南>博文汇总 在MEF之前,人们已经提出了许多依赖注入框架来解决应用的扩展性问题,比如OSGI 实现以Spring 等等.在 Microsoft 的平台上,.NET Fr ...

  5. 【转】MEF程序设计指南四:使用MEF声明导出(Exports)与导入(Imports)

    在MEF中,使用[System.ComponentModel.Composition.ExportAttribute]支持多种级别的导出部件配置,包括类.字段.属性以及方法级别的导出部件,通过查看Ex ...

  6. MEF程序设计指南

    ############################################################################################## ##### ...

  7. Hibernate -- lazy加载

    Hibernate -- lazy加载 hibernate类级别懒加载: lazy:true(默认) //类级别懒加载 //load方法 //class lazy属性 //默认值:true load获 ...

  8. FreeSql (二十五)延时加载

    FreeSql 支持导航属性延时加载,即当我们需要用到的时候才进行加载(读取),支持1对1.多对1.1对多.多对多关系的导航属性. 当我们希望浏览某条订单信息的时候,才显示其对应的订单详细记录时,我们 ...

  9. 【原创】从零开始搭建Electron+Vue+Webpack项目框架(五)预加载和Electron自动更新

    导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...

随机推荐

  1. diskspd的使用

    参数翻译 可测试目标: file_path 文件abc.file #<physical drive number> #1为第一块物理磁盘[谨慎,别拿系统盘测试,一般用于准备投入的数据磁盘测 ...

  2. .CBB 文件 如何打开

    CCB Visual Basic动态按钮配置文件 用SQL server,导入时选择 access,打开后即可.

  3. ORM创建 脚本运行

  4. 通过python给mysql建表

    一.python连接mysql from sqlalchemy import create_engine # 数据库数据 HOSTNAME = '127.0.0.1' # linux本地 PORT = ...

  5. leetcode950

    from queue import Queue class Solution: def deckRevealedIncreasing(self, deck): n = len(deck) que = ...

  6. 5.mybatis实战教程(mybatis in action)之五:与spring3集成(附源码)

    转自:https://blog.csdn.net/nnn9223643/article/details/41962097 在 这一系列文章中,前面讲到纯粹用mybatis 连接数据库, 然后 进行增删 ...

  7. javascript事件之鼠标滚轮(mousewheel)和DOMMouseScroll事件

    javascript事件之鼠标滚轮(mousewheel)和DOMMouseScroll事件 发布时间:2015-02-07   编辑:www.jquerycn.cn 本文学习下,javascript ...

  8. ADO数据库编程入门

    ADO 是目前在Windows环境中比较流行的客户端数据库编程技术. ADO是建立在OLE DB底层技术之上的高级编程接口,因而它兼具有强大的数据处理功能(处理各种不同类型的数据源.分布式的数据处理等 ...

  9. 【Java杂记】Equals 和 hashCode

    equals 和 hashCode含义 equal:判断两个对象是否相等,如果相同,返回true 否则返回false hashcode: 返回一个int数 Object 默认(内部地址转化为一个数字) ...

  10. etcd ui

    https://github.com/henszey/etcd-browser docker build --build-arg http_proxy=http://109.105.4.17:3128 ...