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的延迟加载及元数据相关的内容.在实际的设计开发中,存在着某些对象是不需要在系统运行或者附属对象初始化的时候进行实例化的,只需要在使用到它的时候才会进行实例化,这种方式就可 ...
随机推荐
- iOS:Masonry练习详解
Masonry练习详解 添加约束的方式: 1.通过使用NSLayoutConstraints添加约束到约束数组中,之前必须设置translatesAutoresizingMaskIntoConst ...
- [转载]DIY树莓派之随身工具箱
摆弄树莓派有一年多了,在这里把经验分享给大家,少走弯路. 先放图两张. 搭建目的: wifi信号中转站\网站服务器\IC卡渗透测试\中间人\otr… 基于树莓派3 系统为Kali Linux 2017 ...
- Android手掌抑制功能的实现
近期须要实现一个功能,在Activity中有一个手写区域,为了更好的用户体验,须要满足即使整个手掌放在屏幕上时(android平板,屏幕比較大)也仅仅响应手写区域内的操作,即在支持多点触控的情况下,仅 ...
- 通过案例对SparkStreaming透彻理解三板斧之三
本课将从二方面阐述: 一.解密SparkStreaming Job架构和运行机制 二.解密SparkStreaming容错架构和运行机制 一切不能进行实时流处理的数据都将是无效的数据.在流处理时代,S ...
- Activemq消息确认机制 --转载
转自:http://blog.csdn.net/czp11210/article/details/47022639 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存 ...
- php RSA 加密 与java加密互交,java解密
<? php class encrypt{ var $pub_key; function redPukey() { $pubKey = "MIIDhzCCAm+gAwIBAgIGASY ...
- 后缀数组suffix array
倍增算法,时间复杂度O(nlogn) sa从小到大保存相对大小的下标 理解LSD,x数组,sa数组 char s[maxn]; int sa[maxn],t[maxn],t2[maxn],c[maxn ...
- AngularJs学习笔记(1)——ng-app
众所周知: ng-app 指令用于告诉 AngularJS 应用当前这个元素是根元素.所有 AngularJS 应用都必须要要一个根元素. 只有被具有ng-app属性的DOM元素包含的元素才会受ang ...
- 将 ASP.NET Core 2.0 项目升级至 ASP.NET Core 2.1
主要升级步骤如下: 将 .csproj 项目文件中的 target framework 改为 netcoreapp2.1 <TargetFramework>netcoreapp2.1< ...
- php私有成员private的程序题目
class base { private $member; function __construct() { echo __METHOD__ . "(begin)\n"; $thi ...