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

  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”,其值为“李四”的元数据信息,并且还定义了一个用于承载元数据结构的结构,接下来就可以通过迟延加载导入,进行元数据的获取了。

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);
    }
}

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

    

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

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 = "张三";
    }
}

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

时间: 2024-10-15 09:19:57

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

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

http://www.cnblogs.com/beniao/archive/2010/08/11/1797537.html 在MEF之前,人们已经提出了许多依赖注入框架来解决应用的扩展性问题,比如OSGI 实现以Spring 等等.在 Microsoft 的平台上,.NET Framework 自身内部包含组件模型和 System.Addin.同时存在若干种开源解决方案,包括 SharpDevelop 的 SODA 体系结构和“控制反转”容器(如 Castle Windsor.Structure

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

在MEF中,使用[System.ComponentModel.Composition.ExportAttribute]支持多种级别的导出部件配置,包括类.字段.属性以及方法级别的导出部件,通过查看ExportAttribute的源代码就知道ExportAttribute被定义为Attribute,并为其设置了使用范围. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA18

Hibernate中load()和get()的区别,lazy加载和Eager加载的区别

Hibernate中load()和get()的区别: get():是直接操作数据库,通过id获取数据封装对象,如果没有数据则返回null: load():先在session缓存中查询,如果缓存中不存在,则延迟从数据库中查询,没发现符合条件的记录,则会抛出一个ObjectNotFoundException.在延迟查询中如果session关闭则会抛出no session异常 Hibernate中lazy加载和Eager加载的区别: Eager加载:将当前表和关联的其它表一并查询出来,select的语

图片lazy加载

两种图片lazy加载的方式 第一个By JS中级交流群 成都-猎巫 第二个By 上海-zenki// @description 准备为图片预加载使用的插件// 使用的图片容器css类名为lazy-load-wrap// 图片真实地址为data-lazy-src// 当lazy-load-wrap容器进入视口,则开始替换容器内所有需要延迟加载的图片路径,并更改容器的加载状态//第一种方法$.fn.compassLazyLoad=function(){ var _HEIGHT=window.inne

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

导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更新(六)构建.发布整个项目(包括client和web)(未完待续) 摘要:到目前为止,我们的项目已经具备了PC客户端该有的一些基础功能和调试环境,但是总感觉缺了灵魂,那就是结合实际项目.实际业务的细节处理,缺着吧...这篇文章就介绍一下预加载和自动更新,文字功底有限,如有介绍的不清楚的地方,欢迎留言

NX二次开发-UFUN获取当前会话中加载的部件数量UF_PART_ask_num_parts

1 NX11+VS2013 2 3 #include <uf.h> 4 #include <uf_part.h> 5 #include <uf_ui.h> 6 7 8 //获取当前会话中加载的部件数量 9 int num = UF_PART_ask_num_parts(); 10 11 //打印 12 char msg[256]; 13 sprintf(msg, "当前会话中加载的部件数量为:%d", num); 14 uc1601(msg, 1);

MyBatis入门(五)---延时加载、缓存

一.创建数据库 1.1.建立数据库 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.7.9-log : Database - mybatis ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @[email protec

Spring源码学习(五)bean的加载

加油加油 ?? bean加载的大致过程 1 /** 2 * Return an instance, which may be shared or independent, of the specified bean. 3 * 4 * @param name the name of the bean to retrieve 5 * @param requiredType the required type of the bean to retrieve 6 * @param args argume

spring IOC之篇五 bean的加载

我们终于结束了对XML配置文件的解析,接下来我们要分析bean的加载,即对代码getBean的分析: People p = (People)ctx.getBean("cutesource"); @SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args,