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命名空间的函数,另一种 ...
随机推荐
- gitlab 搭建自己的源代码管理器
首先 gitlab 是不支持 windows.mac os 的,具体支持的系统参照官网的 1.安装虚拟机 ubuntu16.04 需要注意的一点:gitlab 服务器 与 客户端必须在一个局域网内( ...
- 部署自己配置的nginx到kubernetes,并且能通过ingress访问
本文的环境介绍 [root@m-30-1 ~]# kubectl version Client Version: version.Info{Major:"1", Minor:&qu ...
- 读书笔记之Linux系统编程与深入理解Linux内核
前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...
- Batch Normalization--介绍
思考 YJango的前馈神经网络--代码LV3的数据预处理中提到过:在数据预处理阶段,数据会被标准化(减掉平均值.除以标准差),以降低不同样本间的差异性,使建模变得相对简单. 我们又知道神经网络中的每 ...
- Delphi - 子窗体继承父窗体后如何显示父窗体上的控件
1.创建子窗体Form1 File -> New -> Form,新建一个form,在form的单元文件中修改 2.子窗体中引用父窗体单元 uses TFatherForm 3.将子窗体中 ...
- Varnish实现Web站点加速
Varnish 是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang使用3台Varnish代替了原来的12台Squid,性能比以前更好. Varnish 的作者Poul-He ...
- 聊聊fetch
fetch的使用 fetch是一个发起异步请求的新api, 在浏览器(有些不支持)中可以直接使用. Promise fetch(url, init) fetch接收两个参数,第一个参数是请求路径,第二 ...
- SQL注入的优化和绕过
作者:Arizona 原文来自:https://bbs.ichunqiu.com/thread-43169-1-1.html 0×00 ~ 介绍 SQL注入毫无疑问是最危险的Web漏洞之一,因为我们将 ...
- java中的io系统详解
相关读书笔记.心得文章列表 Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字 ...
- css 如何“画”一个抽奖转盘
主要描述的是如何运用 css 绘制一个抽奖转盘,并运用原生 js 实现转盘抽奖效果. 先来张效果图: 布局 一般来说,转盘一般有四个部分组成:外层闪烁的灯.内层旋转的圆盘.圆盘上的中奖结果.指针. 所 ...