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的延迟加载及元数据相关的内容.在实际的设计开发中,存在着某些对象是不需要在系统运行或者附属对象初始化的时候进行实例化的,只需要在使用到它的时候才会进行实例化,这种方式就可 ...
随机推荐
- IP地址后面斜杠加具体数字详解
其实这种形式就是用CIDR(无类别域间路由选择,Classless and Subnet Address Extensions and Supernetting))的形式表示的一个网段,或者说子网. ...
- 【C/C++学院】0723-32位与64位/调戏窗体程序/数据分离算法/内存检索/二分查找法/myVC
[送给在路上的程序猿] 对于一个开发人员而言,能够胜任系统中随意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并能够运用到系统中,由此简化系统的开发,是其架构生涯的第一步. ...
- 【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
在上一篇文章<调用网络API>中,我仅仅讲述了怎样直观的使用API接口以及调用API后返回的结果,本文则从程序实现的角度来实现API的调用.当然本程序的实现也是借助于扇贝网的API接口文档 ...
- Unity3d-XML文件数据解析&JSON数据解析
1.XML文件数据解析:(首先须要导入XMLParser解析器,The latest released download from:http://dev.grumpyferret.com/unity/ ...
- android 完美的tabhost 切换多activity布局
TabHost在很多应用都会使用到,有时候在TabHost添加的Tab中设置view不能满足需求,因为在view中添加如PreferenceActivity相当困难. 之前在一个应用中需要实现使用Ta ...
- Swift 泛型參数
原文:http://www.cocoachina.com/newbie/basic/2014/0612/8802.html 本页内容包含:泛型形參语句和泛型实參语句 本节涉及泛型类型.泛型函数以及泛型 ...
- 深入浅出理解之 onInterceptTouchEvent与onTouchEvent
参考:http://blog.csdn.net/android_tutor/article/details/7193090 与 http://www.cnblogs.com/kingcent/ ...
- C语言-gdb调试工具详解
回车 重复上一次命令 产生可调试的可执行文件:gcc -g main.c -o main, 必须加上-g选线, 表示在可执行文件中加入源文件信息, 但并不是将源文件嵌入可执行文件, 所以在调试时必须保 ...
- C语言-Makefile经典教程(掌握这些足够)
makefile很重要 什么是makefile? 或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional 的 ...
- hystrix-turbine实现多服务监控
原文地址:http://www.cnblogs.com/skyblog/p/5633757.html 1. 概述 Demo地址:http://git.oschina.net/zhou666/spr ...