原文:MEF 插件式开发 - 小试牛刀

目录


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 插件式开发 - WPF 初体验

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

  2. MEF 插件式开发之 小试牛刀

    MEF 简介 Managed Extensibility Framework 即 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. 洛谷 P1984 [SDOI2008]烧水问题

    洛谷 P1984 [SDOI2008]烧水问题 题目描述 把总质量为1kg的水分装在n个杯子里,每杯水的质量均为(1/n)kg,初始温度均为0℃.现需要把每一杯水都烧开.我们可以对任意一杯水进行加热. ...

  2. php实现 字符个数统计

    php实现 字符个数统计 一.总结 一句话总结: 1.php字符转ascii码函数? ord() 6 if(ord($input[$i]) < 128 and 0 < ord($input ...

  3. js如何实现动态点击改变单元格颜色?

    js如何实现动态点击改变单元格颜色? 一.总结 1.通过table的rows属性,遍历表格所有行,然后通过cells属性,遍历每一行中的单元格. 2.遍历的过程中,动态的为每一个单元格定义单击事件,改 ...

  4. PHP移动互联网开发笔记(7)——MySQL数据库基础回顾[1]

    一.数据类型 1.整型 数据类型 存储空间 说明 取值范围 TINYINT 1字节 非常小的整数 带符号值:-128~127无符号值:0~255 SMALLINT 2字节 较小的整数 带符号值:-32 ...

  5. TI_DSP_SRIO - Doorbell原理

    前文介绍到SRIO有多种类型的包,当中包括了Doorbell包,Doorbell是一种高速的通知类型的短消息,包头和携带信息都非常短,用于master srio设备通知slave srio设备,可用于 ...

  6. 微服务学习笔记(2)——使用Consul 实现 MagicOnion(GRpc) 服务注册和发现

    原文:微服务学习笔记(2)--使用Consul 实现 MagicOnion(GRpc) 服务注册和发现 1.下载打开Consul 笔者是windows下面开发的(也可以使用Docker). 官网下载w ...

  7. 【u109】数字生成游戏(gen)

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小明完成了这样一个数字生成游戏,对于一个不包含0的数字s来说,有以下3种生成新的数的规则: 1. 将s ...

  8. 在向server发送请求时发生传输级错误。 (provider: 共享内存提供程序, error: 0 - 管道的还有一端上无不论什么进程。

    作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/36425825 SQL Server 2008 + VS2010 用C#编写的代 ...

  9. BZOJ 3932 - 主席树

    传送门 题目分析 在只打会主席树模板的情况下做了这道题,也算是深有体会. 首先任务可以差分:一个任务是(s, e, p), 则在s处+1, 在e+1处-1,符合前缀.但是我们要查询指定时间的前k任务之 ...

  10. 【codeforces 791B】Bear and Friendship Condition

    [题目链接]:http://codeforces.com/contest/791/problem/B [题意] 给你m对朋友关系; 如果x-y是朋友,y-z是朋友 要求x-z也是朋友. 问你所给的图是 ...