MEF 简介

Managed Extensibility Framework 即 MEF 是用于创建轻量、可扩展应用程序的库。 它让应用程序开发人员得以发现和使用扩展且无需配置。 它还让扩展开发人员得以轻松地封装代码并避免脆弱的紧密依赖性。 MEF 让扩展不仅可在应用程序内重复使用,还可以跨程序重复使用。

在进行传统的 C/S 端开发,如果项目不是特别复杂,常规的开发模式还是可以应对的。但是一旦场景复杂度提升,一个小小业务功能的修改就需要更新整个客户端,这个对于开发者来说是不能忍受的。因此微软为我们引入了 MEF 的开发模式。允许我们将众多的业务模块拆分开来设计成独立的 DLL,然后由客户端来进行统一加载,这样就能解决上述我们所说的痛点。

实践出真知

创建一个高扩张的 MEF 框架涉及的技术点较多。为了方便初学者能较快理解,上手实践,我这里主要通过 3 个方面来进行相关叙述。

面向接口编程

如果你还不能理解什么是面向接口编程的话,那你应该还不能区分抽象类和接口之间的区别。其实在刚开始的时候我也不是很能理解,直到我看到了一句话:抽象类规定了你是什么,接口规定了你能干什么,只要你能理解这句话,那么你应该就明白什么是面向接口编程,这种编程方式的好处是统一化了业务的暴露方式,方便外部使用。下面我们看一个简单的例子。

public interface IMessage
{
void Send();
} public class EmailService : IMessage
{
public void Send()
{
Console.WriteLine("Email Send Message");
}
} public class SMSService : IMessage
{
public void Send()
{
Console.WriteLine("SMS Send Message");
}
} class Program
{
static void Main(string[] args)
{
IMessage email = new EmailService();
email.Send(); IMessage sms = new SMSService();
sms.Send(); Console.ReadKey();
}
}

上述代码中,我们创建了一个 IPlugin 的接口,接口定义了一个 ShowPluginName() 方法,然后我们再定义了两个独立的类来分别继承该接口并实现相应的接口函数。在主函数中,我们只需要定义一个接口类型的对象,然后接收一个具体的类型实例,函数就会输出对应的正确信息。这样编程的好处就不言而喻了。代码很简单,这里就不过多描述。输出结果如下图所示

控制反转(IOC)

所谓控制反转,就是将对象初始化的控制权交出去。要实现控制反转,我们需要有面向接口编程的接口,同样的,这里也是展示一个代码段来叙述。

public interface IMessage
{
void Send();
} public class EmailService : IMessage
{
public void Send()
{
Console.WriteLine("Email Send Message");
}
} public class SMSService : IMessage
{
public void Send()
{
Console.WriteLine("SMS Send Message");
}
} public static class Factory
{
public static EmailService GetEmailService() => new EmailService(); public static SMSService GetSMSService() => new SMSService();
} class Program
{
static void Main(string[] args)
{
Console.WriteLine("DependencyService:");
DependencyService(); Console.WriteLine(); Console.WriteLine("InversionDependencyService:");
InversionDependencyService(); Console.ReadKey();
} static void DependencyService()
{
EmailService fooEmailService = new EmailService();
fooEmailService.Send();
}
static void InversionDependencyService()
{
IMessage fooMessage = Factory.GetEmailService();
fooMessage.Send();
fooMessage = Factory.GetSMSService();
fooMessage.Send();
}
}

在这个例子中,我们通过工厂模式创建具体的服务,然后供主程序来调用,代码依然很简单,分别用传统创建服务的方式和 控制反转的方式来进行对比。程序输出如下

构建入门级 MEF

有了上面两个知识点做铺垫,我们可以开始创建一个入门级的 MEF 示例程序。想要在程序中使用 MEF 的话需要引入如下程序集

  • System.ComponentModel.Composition

这里还是以控制台程序来展示。项目结构如下图所示

  • MefSample.Core:核心接口定义在该项目中
  • MefSample.EmailService:插件,需要引用 MefSample.Core 和 System.ComponentModel.Composition
  • MefSample.SMSService:插件,需要引用 MefSample.Core 和 System.ComponentModel.Composition
  • MefSample:主程序,需要引用 MefSample.Core 和 System.ComponentModel.Composition

注意:上述所有项目程序的输出目录需要保持一致

MefSample.Core 代码段

public interface IMessage
{
void Send();
}

MefSample.EmailService 代码段

[Export(typeof(IMessage))]
public class EmailService: IMessage
{
public void Send()
{
Console.WriteLine("Email Send Message");
}
}

MefSample.SMSService 代码段

[Export(typeof(IMessage))]
public class SMSService : IMessage
{
public void Send()
{
Console.WriteLine("SMS Send Message");
}
}

MefSample 代码段

class Program
{
static void Main(string[] args)
{
var dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
var catalog = new DirectoryCatalog(dir.FullName, "*.dll");
using (CompositionContainer container = new CompositionContainer(catalog))
{
IEnumerable<IMessage> messages = container.GetExportedValues<IMessage>();
if (messages != null)
{
foreach (var message in messages)
{
message.Send();
}
}
}
Console.ReadKey();
}
}

仔细观察的话,其实上述代码还是挺简单的, 我这里使用了 DirectoryCatalog 的方式来寻找目标插件,感兴趣的朋友可以试试其他方式:AggregateCatalogAssemblyCatalogDirectoryCatalog。当然,你也可以自定义。程序输出结果如下图所示

好了,程序写到这里相信你对 MEF 也多少有些了解。我没有过多的讲解抽象理论,而是更多地通过代码来描述我所想要说的。在下篇文章中,我将会简单讲述一下 MEF 在 WPF 中的入门使用,方便初学者更上一层楼。加油,共勉!

相关参考

MEF 插件式开发之 小试牛刀的更多相关文章

  1. MEF 插件式开发 - 小试牛刀

    原文:MEF 插件式开发 - 小试牛刀 目录 MEF 简介 实践出真知 面向接口编程 控制反转(IOC) 构建入门级 MEF 相关参考 MEF 简介 Managed Extensibility Fra ...

  2. MEF 插件式开发 - WPF 初体验

    原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...

  3. [MEF插件式开发] 一个简单的例子

    偶然在博客园中了解到这种技术,顺便学习了几天. 以下是搜索到一些比较好的博文供参考: MEF核心笔记 <MEF程序设计指南>博文汇总 先上效果图 一.新建解决方案 开始新建一个解决方案Me ...

  4. [转][MEF插件式开发] 一个简单的例子

    偶然在博客园中了解到这种技术,顺便学习了几天. 以下是搜索到一些比较好的博文供参考: MEF核心笔记 <MEF程序设计指南>博文汇总 先上效果图 一.新建解决方案 开始新建一个解决方案Me ...

  5. MEF 插件式开发之 WPF 初体验

    MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场景中,C/S 和 B/S 中都有相应的使用场景,其中包括但不限于 ASP.NET MVC .ASP WebForms.WPF ...

  6. MEF 插件式开发之 DotNetCore 中强大的 DI

    背景叙述 在前面几篇 MEF 插件式开发 系列博客中,我分别在 DotNet Framework 和 DotNet Core 两种框架下实验了 MEF 的简单实验,由于 DotNet Framewor ...

  7. MEF 插件式开发之 DotNetCore 初体验

    背景叙述 在传统的基于 .Net Framework 框架下进行的 MEF 开发,大多是使用 MEF 1,对应的命名空间是 System.ComponentModel.Composition.在 Do ...

  8. 也来学学插件式开发续-利用MEF

    前面一个博客:也来学学插件式开发中很多朋友留言说可以用MEF来实现.于是我就试着用MEF实现了一下. 步骤和上一篇差不多,只是加载插件的方式有所不同.这只是一个自己的示例程序,肯定有很多不足之处,欢迎 ...

  9. C#学习笔记-----基于AppDomain的"插件式"开发

    很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统, ...

随机推荐

  1. PHP 文件处理----fopen(),fclose(),feof(),fgets(),fgetc()

    fopen() 函数用于在 PHP 中打开文件. 打开文件 fopen() 函数用于在 PHP 中打开文件. 此函数的第一个参数含有要打开的文件的名称,第二个参数规定了使用哪种模式来打开文件: < ...

  2. docker中gitlab-runner配置

    1.启动gitlab-runner docker run -d --name gitlab-runner --restart always \ -v /opt/data/gitlab-runner/c ...

  3. 一个简单的将Markdown二级标题进行排序的脚本

    我在写博客<Linux的1000个命令>的时候,相对二级标题进行一下排序,方便阅读和查找,于是就有了这个小程序. #! /usr/bin/env python3 import os imp ...

  4. Swift5 语言指南(十一) 结构和类

    结构和类是通用的,灵活的结构,它们成为程序代码的构建块.您可以使用与定义常量,变量和函数相同的语法来定义属性和方法,以便为结构和类添加功能. 与其他编程语言不同,Swift不要求您为自定义结构和类创建 ...

  5. java相关技术问答(一)

    网上一些没有标准答案的面试题,我自己做的解答总结,有任何异议可以提出来~^_^,不断更新中... Springboot除了自动配置与传统的spring还有哪些不同 传统的springweb项目需要部署 ...

  6. 谈谈 JavaScript 的正则表达式

    一.背景 最近在做 CMS 系统中不同身份登录用户的权限管理,涉及到对 api 路径的识别去判断是否放行.以前对正则表达式都是敬而远之,要用到的话都是直接复制粘贴现成网上的表达式,看也看不太懂,借这次 ...

  7. Eclipse中java内存溢出

    1.点击Window --->Preferences,如下图  

  8. LeetCode--No.010 Regular Expression Matching

    10. Regular Expression Matching Total Accepted: 89193 Total Submissions: 395441 Difficulty: Hard Imp ...

  9. Centos 7 安装 rabbitmq

    1.安装erlang rabbitmq 官方下载地址 "http://www.rabbitmq.com/download.html" ,选择"RHEL, CentOS, ...

  10. JAR(Spring Boot)应用的后台运行配置

    酱油一篇,整理一下关于Spring Boot后台运行的一些配置方式.在介绍后台运行配置之前,我们先回顾一下Spring Boot应用的几种运行方式: 运行Spring Boot的应用主类 使用Mave ...