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命名空间的函数,另一种 ...
随机推荐
- Crontab定时执行Oracle存储过程
Crontab定时执行Oracle存储过程 需求描述 我们有一个Oracle的存储过程,里面是每个月需要执行一下,生成报表,然后发送给业务部门,这一个功能我们有实现在系统的前台界面(如图1-1),但是 ...
- Beta冲刺 (4/7)
Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 共享编辑文章的后端数据处理 展示Gi ...
- 内置函数_map()、reduce()、filter()
map().reduce().filter() map()内置函数把一个函数func依次映射到序列或迭代器对象的每个元素上,并返回一个可迭代的map对象作为结果,map对象中每个元素是原序列中元素经过 ...
- Centos7部署Kubernetes集群
目录贴:Kubernetes学习系列 1.环境介绍及准备: 1.1 物理机操作系统 物理机操作系统采用Centos7.3 64位,细节如下. [root@localhost ~]# uname -a ...
- 迁移桌面程序到MS Store(5)——.NET Standard
接下来的几篇,我想讨论下迁移桌面程序到MS Store,可以采用的比较常见.通用性比较强的实施步骤和分层架构. 通常商业项目一般都是不断的迭代,不太可能突然停止更新现有的桌面版本,然后花很长时间从头来 ...
- 使用netstat命令查看端口的使用情况
Windows如何查看端口占用情况操作步骤如下: 开始--运行--cmd 进入命令提示符,输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管 ...
- Android开发 - 掌握ConstraintLayout(五)偏差(Bias)
比如实现这样一个场景: "在屏幕宽度的1/4的地方放置一个View" 使用传统布局时,实现按照屏幕的宽度(高度),或者相对两个View之间距离的一个比例来进行布局,就显得非常麻烦, ...
- typescript handbook 学习笔记4
概述 这是我学习typescript的笔记.写这个笔记的原因主要有2个,一个是熟悉相关的写法:另一个是理清其中一些晦涩的东西.供以后开发时参考,相信对其他人也有用. 学习typescript建议直接看 ...
- 基于vue的颜色选择器vue-color-picker
项目中有用到颜色选择器的童鞋们可以看过来了 关于color-picker的jquery的插件是有蛮多,不过vue组件没有吧,反正我没有找到, 虽然element-ui里面有这个,但是你愿意为了一个小功 ...
- Spring 中初始化一个Bean对象时依赖其他Bean对象空指针异常
1. Bean依赖关系 一个配置类的Bean,一个实例Bean: 实例Bean初始化时需要依赖配置类的Bean: 1.1 配置类Bean @ConfigurationProperties(prefix ...