MEF 插件式开发之 DotNetCore 初体验
背景叙述
在传统的基于
.Net Framework框架下进行的 MEF 开发,大多是使用 MEF 1,对应的命名空间是 System.ComponentModel.Composition。在DotNet Core中,微软为了伟大的跨平台策略,引入了 MEF 2,其对应的命名空间是 System.Composition,这个需要开发者自己在 Nuget 上进行下载安装 Microsoft.Composition。2 与 1 相比,无论是在支持平台上还是性能上都有改进,值得我们探讨一下。
动手实验
实验1:在 DotNetCore 控制台程序中尝试使用 MEF2
首先,我们创建一个 DotNet Core 控制台应用程序,然后为其添加 MEF2 对应的 Package:Microsoft.Composition;
然后,我们创建一个示例接口:
public interface IMessageSender
{
void Send(string message);
}
接着,我们再创建一个示例类来实现该接口,并尝试将其导出:
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
最后,我们在主程序中进行调用:
class Program
{
static void Main(string[] args)
{
//寻找主程序命名空间
var assembiles = new[] { typeof(Program).GetTypeInfo().Assembly };
//配置 MEF 容器
var configuration = new ContainerConfiguration()
.WithAssembly(typeof(Program).GetTypeInfo().Assembly);
using (var container = configuration.CreateContainer())
{
//依据相应接口获取导出的具体类
IMessageSender messageSender = container.GetExport<IMessageSender>();
messageSender.Send("Hello MEF2");
}
Console.ReadKey();
}
}
此时,如果一切正常的话,程序会输入如下结果:

实验2:在 DotNetCore 控制台程序中尝试使用 MEF2 加载外部组件
由于微软在 DotNetCore 中为开发者提供了新的程序集加载方式 AssemblyLoadContext。它允许多次加载相同的程序集,并创建相互独立的副本,并且它比 AppDomain 重量轻得多。因此我在本次实验中,笔者尝试使用这种新的加载方式进行实验。
首先,我们创建一个如下图所示的解决方案:

- DotNetCoreMEF:控制台程序,安装
Microsoft.Composition,并引用DotNetCoreMEF.Core; - DotNetCoreMEF.Core:核心类库,用于定义相关接口;
- DotNetCoreMEF.Plugin1:插件类库,安装
Microsoft.Composition,并引用DotNetCoreMEF.Core; - DotNetCoreMEF.Plugin2:插件类库,安装
Microsoft.Composition,并引用DotNetCoreMEF.Core;
注意:请确保上述项目的生成目录保持一致。
相关示例代码如下所示:
IMessageSender.cs
public interface IMessageSender
{
void Send(string message);
}
EmailSender.cs
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine($"Email:{message}");
}
}
SMSSender.cs
[Export(typeof(IMessageSender))]
public class SMSSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine($"SMS:{message}");
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
var assembiles = Directory.GetFiles(AppContext.BaseDirectory, "*.dll", SearchOption.TopDirectoryOnly)
.Select(AssemblyLoadContext.Default.LoadFromAssemblyPath);
var conventions = new ConventionBuilder();
conventions.ForTypesDerivedFrom<IMessageSender>()
.Export<IMessageSender>()
.Shared();
var configuration = new ContainerConfiguration()
.WithAssemblies(assembiles, conventions);
using (var container = configuration.CreateContainer())
{
IEnumerable<IMessageSender> senders = container.GetExports<IMessageSender>();
foreach (var sender in senders)
{
sender.Send("Hello World");
}
}
Console.ReadKey();
}
}
此时,我们将项目全部重新编译一下,可通过 VS 调试运行,看到相应的输出结果。当然,我们也可以通过命令行的方式运行程序,前提是我们需要将我们的程序发布一下。发布好后我们可以执行 dotnet DotNetCoreMEF.dll 看到输出结果:

总结
上述展示的只是 MEF 在 DotNet Core 中的简单应用,其中需要注意的是 AssemblyLoadContext ,此外,关于模块的 延迟记载 和 元数据的获取 ,感兴趣的朋友可参考我之前的一篇博客进行参考:MEF 插件式开发 - WPF 初体验。
其实,如果对 DotNet Core 有一定了解的朋友是知道的,上述这种方式虽然实现了插件式的开发模式,但是并没有完全发挥 DotNet Core 本身所具有优势:内置 DI。所以,我们完全可以使用更高效的方式来实现。在下篇博客中,我们将感受一下 DotNet Core 中强大的 DI 。
相关参考
- Managed Extensibility Framework (MEF)
- BCL Team Blog
- Using MEF in .NET Core
- Using MEF in .NET Core
- best-practices-for-assembly-loading
- 【.NET 深呼吸】在 .net core app 中使用 Composition
- .NET Core application deployment
MEF 插件式开发之 DotNetCore 初体验的更多相关文章
- MEF 插件式开发之 WPF 初体验
MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场景中,C/S 和 B/S 中都有相应的使用场景,其中包括但不限于 ASP.NET MVC .ASP WebForms.WPF ...
- MEF 插件式开发之 DotNetCore 中强大的 DI
背景叙述 在前面几篇 MEF 插件式开发 系列博客中,我分别在 DotNet Framework 和 DotNet Core 两种框架下实验了 MEF 的简单实验,由于 DotNet Framewor ...
- Android插件化开发之OpenAtlas生成插件信息列表
上一篇文章.[Android插件化开发之Atlas初体验]( http://blog.csdn.net/sbsujjbcy/article/details/47446733),简单的介绍了使用Atla ...
- MEF 插件式开发 - WPF 初体验
原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...
- MEF 插件式开发 - 小试牛刀
原文:MEF 插件式开发 - 小试牛刀 目录 MEF 简介 实践出真知 面向接口编程 控制反转(IOC) 构建入门级 MEF 相关参考 MEF 简介 Managed Extensibility Fra ...
- [MEF插件式开发] 一个简单的例子
偶然在博客园中了解到这种技术,顺便学习了几天. 以下是搜索到一些比较好的博文供参考: MEF核心笔记 <MEF程序设计指南>博文汇总 先上效果图 一.新建解决方案 开始新建一个解决方案Me ...
- MEF 插件式开发之 小试牛刀
MEF 简介 Managed Extensibility Framework 即 MEF 是用于创建轻量.可扩展应用程序的库. 它让应用程序开发人员得以发现和使用扩展且无需配置. 它还让扩展开发人员得 ...
- [转][MEF插件式开发] 一个简单的例子
偶然在博客园中了解到这种技术,顺便学习了几天. 以下是搜索到一些比较好的博文供参考: MEF核心笔记 <MEF程序设计指南>博文汇总 先上效果图 一.新建解决方案 开始新建一个解决方案Me ...
- jQuery插件的开发之$.extend(),与$.fn.extend()
jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种 ...
随机推荐
- ScriptOJ-safeGet#99
const safeGet = (data, path) => { if(!path) return undefined; const pathArr = path.split('.'); le ...
- HTML里面form表单name,action,method,target,enctype等属性用法
HTML里面的form表单里面的name,target,enctype,method以及action的用法 HML表单HTML里面的表单是HTML页面与浏览器交互的重要手段,表单主要提交一些客户端的数 ...
- linux下 /usr/bin/ld: 找不到 -ldhnetsdk的解决方法
linux下使用Qt编译程序的时候,安装了程序自带的链接库之后,仍然上报这个错误, 发现系统上报这个错误: /usr/bin/ld: 找不到 -ldhnetsdk 经过仔细的定位,终于解决了,这里把思 ...
- 使用Ansible实现数据中心自动化运维管理
长久以来,IT 运维在企业内部一直是个耗人耗力的事情.随着虚拟化的大量应用.私有云.容器的不断普及,数据中心内部的压力愈发增加.传统的自动化工具,往往是面向于数据中心特定的一类对象,例如操作系统.虚拟 ...
- vue 自学笔记(6) axios的使用
前情提要:axios 的使用 axios是一个ajax 的包,主要在node.js 使用 axios 的官网 https://www.kancloud.cn/yunye/axios/234845 一: ...
- Python模块——xml
xml模块 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单, 不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行 ...
- C# 窗体间传值
Form1: 父窗体, Form2: 子窗体. 1.父窗体接收子窗体的返回值: public partial class Form1: Form { private void btnOpen_Clic ...
- jq版本的checkbox有radio的单选效果(可得到value值)
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>复 ...
- Centos 7 安装 rabbitmq
1.安装erlang rabbitmq 官方下载地址 "http://www.rabbitmq.com/download.html" ,选择"RHEL, CentOS, ...
- c++ vector的内存释放
c++中vector的一个特点是: 内存空间只会增长,不会减小.即为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都挨着前一个元素存储.设想,如果每次vector添加一个新元素 ...