MEF笔记 之延迟加载
文章参考:在MEF中实现延迟加载部件 作者:TianFang
仅有一个服务提供者时候
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting; namespace 延迟加载
{
interface ILogger
{
void Log(string message);
}
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public void Log(string message)
{ Console.WriteLine("logger 1" + message);
}
}
class Host
{
[Import]
//延迟加载
Lazy<ILogger> _logger;
//非延迟加载
//ILogger _logger;
public Host()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog); //如果不是延迟加载的话这儿会创建ConsoleLogger对象
container.ComposeParts(this);
//非延迟加载
//_logger.Log("logworld");
//延迟加载
_logger.Value.Log("hello world"); }
}
}
当某一组件并不是立刻需要使用,或者内存开销很大。影响程序加载的速度。比如当程序启动的时候。这个时候我们可以使用延迟加载,也就是只有当程序用到的时候才会去加载该部件。我们可以使用Lazy<T>来标记导入的类型。这样就简单的实现了延迟加载。
注意如果使用Lazy<T>来标记对象类型的话,需要通该实例的Value属性调用实例方法 _logger.Value.Log("hello world");
如果是非延迟加载

如果延迟加载:

当有多个服务提供者的时候
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延迟加载
{
interface ILogger
{
void Log(string message);
}
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("ConsoleLogger " + message);
}
} [Export(typeof(ILogger))]
class DbLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("DbLogger " + message);
}
} class Host
{ //非延迟加载
//[ImportMany]
//ILogger[] _logger = null;
//延迟加载
[ImportMany]
Lazy<ILogger>[] _Lazylogger = null;
public Host()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
//非延迟加载此时会创建所有对象
container.ComposeParts(this);
//非延迟加载
//_logger.FirstOrDefault(i => i is DbLogger).Log("hello world");
//延迟加载,当调用的时候才创建对象,
//但是因为这儿有一个遍历,所以当调用一个对象的时候就会创建所以对象
_Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
}
}
}
此时可以用ImportMany标记导入,同时用Lazy<T>包装我们的导入类型。但是此时有个问题,就是当我们如果通过类型遍历多个对象寻找可用导入时候,会创建所有对象。所以此时我们可以用元数据来判断是否使我们需要的导入。
通过元数据匹配需要的导入
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延迟加载
{
interface ILogger
{
void Log(string message);
}
//通过标记元数据来标记导出服务
[ExportMetadata("Name", "Console Logger")]
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("ConsoleLogger " + message);
}
}
//通过标记元数据来标记导出服务
[ExportMetadata("Name", "DbLogger")]
[Export(typeof(ILogger))]
class DbLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("DbLogger " + message);
}
}
public interface ILoggerData
{
string Name { get; }
}
class Host
{
//延迟加载
[ImportMany]
Lazy<ILogger,ILoggerData>[] _Lazylogger = null;
public Host()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
//非延迟加载此时会创建所有对象
container.ComposeParts(this);
//延迟加载,当调用的时候才创建对象,
//但是因为这儿有一个遍历,所以当调用一个对象的时候就会创建所以对象
//_Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
_Lazylogger.FirstOrDefault(i => i.Metadata.Name == "DbLogger").Value.Log("DbLogger"); }
}
}

通过元数据可以匹配我们需要的导出服务。但是,通过单纯的标记 [ExportMetadata("Name", "DbLogger")]很麻烦,而且属性笔记多的时候代码也不整洁。对此我们可以封装一个元数据特性
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延迟加载
{
interface ILogger
{
void Log(string message);
}
//通过标记元数据来标记导出服务
[LoggerData("Console Logger")]
[Export(typeof(ILogger))]
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("ConsoleLogger " + message);
}
}
//通过标记元数据来标记导出服务
[LoggerData("DbLogger")]
[Export(typeof(ILogger))]
class DbLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("DbLogger " + message);
}
}
public interface ILoggerData
{
string Name { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
class LoggerDataAttribute : Attribute, ILoggerData
{
public string Name { get; private set; } public LoggerDataAttribute(string name)
{
this.Name = name;
}
}
class Host
{
//延迟加载
[ImportMany]
Lazy<ILogger, ILoggerData>[] _Lazylogger = null;
public Host()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
//非延迟加载此时会创建所有对象
container.ComposeParts(this);
//延迟加载,当调用的时候才创建对象,
//但是因为这儿有一个遍历,所以当调用一个对象的时候就会创建所以对象
//_Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
_Lazylogger.FirstOrDefault(i => i.Metadata.Name == "DbLogger").Value.Log("DbLogger"); }
}
}
本文地址:http://www.cnblogs.com/santian/p/4357324.html
博客地址:http://www.cnblogs.com/santian/
MEF笔记 之延迟加载的更多相关文章
- 在MEF中实现延迟加载部件(转)
在MEF的宿主中,当我们通过Import声明导入的对象时,组装(Compose)的时候会创建该对象.例如: interface ILogger { void Log(string ...
- 在MEF中实现延迟加载部件
在MEF的宿主中,当我们通过Import声明导入的对象时,组装(Compose)的时候会创建该对象.例如: interface ILogger { void Log(string ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- MEF的学习笔记
为什么要使用MEF 在商业应用软件开发过程中,对于各个软件项目,都需要建立相应的系统框架,为了更好的规范系统的开发,提高生产效率,应该在公司级别制定相应的API标准.这些API标准将站在系统架构层次, ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...
- C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)
上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...
- C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...
- [MEF]第03篇 MEF延迟加载导出部件及元数据
一.演示概述此演示介绍了MEF的延迟加载及元数据相关的内容.在实际的设计开发中,存在着某些对象是不需要在系统运行或者附属对象初始化的时候进行实例化的,只需要在使用到它的时候才会进行实例化,这种方式就可 ...
随机推荐
- Discuz! 6.x/7.x 全局变量防御绕过漏洞
受影响产品: Discuz! 6.x/7.x 漏洞描述: 由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏 ...
- FL2440 rt3070模块station模式动态获取IP地址
---------------------------------------------------------------------------------------------------- ...
- Hibernate参数设置一览表
属性名 用途 hibernate.dialect 一个Hibernate Dialect类名允许Hibernate针对特定的关系数据库生成优化的SQL. 取值 full.classname.of.Di ...
- http://blog.csdn.net/rosten/article/details/17068285
http://blog.csdn.net/rosten/article/details/17068285
- win 8 远程桌面文件复制问题(图)
用win7连接远程桌面.能够非常方便的在宿主机之间文件复制粘贴. 但用win8.1远程连接桌面时,却发现不能拷贝文件了.查看网上资料,最后总结实现此步骤例如以下: win+R,执行mstsc.例如以下 ...
- 【招聘App】—— React/Nodejs/MongoDB全栈项目:socket.io&聊天实现
前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...
- WCF调试异常信息:ServiceHost 仅支持类服务类型
"/CommonHelpServices"应用程序中的server错误. ServiceHost 仅支持类服务类型. 说明: 运行当前 Web 请求期间,出现未经处理的异常. 请检 ...
- perl学习笔记——字符串和排序
用index查找子字符串 查找子字符串在主字符串中的相对位置.如: $where=index($big,$small); 注意index是从0开始的,如果查找不到就会返回-1: 加入第三个参数来指定开 ...
- 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-可以用软件自带NC工具驱动但是程序无法让电机转动怎么办
新建一个项目,当扫描的时候务必勾选YES,使用网上最新的XML文件 如果不使用,则有些设备可能被扫描出来是无效的(图标不正常) 如果完全删除XML描述文件,可能也能扫描出来,而且可以用Twin ...
- C#秘密武器之泛型
一.简介: 很多初学者在刚开始接触泛型的时候会比较难理解泛型,在这里先把 “泛型”当作一个形容词,这样就方便理解了,因为很多东西都可以是泛型的!比如:“泛型的类”,“泛型的方法”,“泛型的接口”,“泛 ...