背景叙述

在传统的基于 .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 。

相关参考

MEF 插件式开发之 DotNetCore 初体验的更多相关文章

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

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

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

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

  3. Android插件化开发之OpenAtlas生成插件信息列表

    上一篇文章.[Android插件化开发之Atlas初体验]( http://blog.csdn.net/sbsujjbcy/article/details/47446733),简单的介绍了使用Atla ...

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

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

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

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

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

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

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

    MEF 简介 Managed Extensibility Framework 即 MEF 是用于创建轻量.可扩展应用程序的库. 它让应用程序开发人员得以发现和使用扩展且无需配置. 它还让扩展开发人员得 ...

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

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

  9. jQuery插件的开发之$.extend(),与$.fn.extend()

        jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种 ...

随机推荐

  1. Crontab定时执行Oracle存储过程

    Crontab定时执行Oracle存储过程 需求描述 我们有一个Oracle的存储过程,里面是每个月需要执行一下,生成报表,然后发送给业务部门,这一个功能我们有实现在系统的前台界面(如图1-1),但是 ...

  2. Beta冲刺 (4/7)

    Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 共享编辑文章的后端数据处理 展示Gi ...

  3. 内置函数_map()、reduce()、filter()

    map().reduce().filter() map()内置函数把一个函数func依次映射到序列或迭代器对象的每个元素上,并返回一个可迭代的map对象作为结果,map对象中每个元素是原序列中元素经过 ...

  4. Centos7部署Kubernetes集群

    目录贴:Kubernetes学习系列 1.环境介绍及准备: 1.1 物理机操作系统 物理机操作系统采用Centos7.3 64位,细节如下. [root@localhost ~]# uname -a ...

  5. 迁移桌面程序到MS Store(5)——.NET Standard

    接下来的几篇,我想讨论下迁移桌面程序到MS Store,可以采用的比较常见.通用性比较强的实施步骤和分层架构. 通常商业项目一般都是不断的迭代,不太可能突然停止更新现有的桌面版本,然后花很长时间从头来 ...

  6. 使用netstat命令查看端口的使用情况

    Windows如何查看端口占用情况操作步骤如下: 开始--运行--cmd 进入命令提示符,输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管 ...

  7. Android开发 - 掌握ConstraintLayout(五)偏差(Bias)

    比如实现这样一个场景: "在屏幕宽度的1/4的地方放置一个View" 使用传统布局时,实现按照屏幕的宽度(高度),或者相对两个View之间距离的一个比例来进行布局,就显得非常麻烦, ...

  8. typescript handbook 学习笔记4

    概述 这是我学习typescript的笔记.写这个笔记的原因主要有2个,一个是熟悉相关的写法:另一个是理清其中一些晦涩的东西.供以后开发时参考,相信对其他人也有用. 学习typescript建议直接看 ...

  9. 基于vue的颜色选择器vue-color-picker

    项目中有用到颜色选择器的童鞋们可以看过来了 关于color-picker的jquery的插件是有蛮多,不过vue组件没有吧,反正我没有找到, 虽然element-ui里面有这个,但是你愿意为了一个小功 ...

  10. Spring 中初始化一个Bean对象时依赖其他Bean对象空指针异常

    1. Bean依赖关系 一个配置类的Bean,一个实例Bean: 实例Bean初始化时需要依赖配置类的Bean: 1.1 配置类Bean @ConfigurationProperties(prefix ...