背景叙述

在传统的基于 .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. gitlab 搭建自己的源代码管理器

    首先  gitlab 是不支持 windows.mac os 的,具体支持的系统参照官网的 1.安装虚拟机 ubuntu16.04 需要注意的一点:gitlab 服务器 与 客户端必须在一个局域网内( ...

  2. 部署自己配置的nginx到kubernetes,并且能通过ingress访问

    本文的环境介绍 [root@m-30-1 ~]# kubectl version Client Version: version.Info{Major:"1", Minor:&qu ...

  3. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  4. Batch Normalization--介绍

    思考 YJango的前馈神经网络--代码LV3的数据预处理中提到过:在数据预处理阶段,数据会被标准化(减掉平均值.除以标准差),以降低不同样本间的差异性,使建模变得相对简单. 我们又知道神经网络中的每 ...

  5. Delphi - 子窗体继承父窗体后如何显示父窗体上的控件

    1.创建子窗体Form1 File -> New -> Form,新建一个form,在form的单元文件中修改 2.子窗体中引用父窗体单元 uses TFatherForm 3.将子窗体中 ...

  6. Varnish实现Web站点加速

    Varnish 是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang使用3台Varnish代替了原来的12台Squid,性能比以前更好. Varnish 的作者Poul-He ...

  7. 聊聊fetch

    fetch的使用 fetch是一个发起异步请求的新api, 在浏览器(有些不支持)中可以直接使用. Promise fetch(url, init) fetch接收两个参数,第一个参数是请求路径,第二 ...

  8. SQL注入的优化和绕过

    作者:Arizona 原文来自:https://bbs.ichunqiu.com/thread-43169-1-1.html 0×00 ~ 介绍 SQL注入毫无疑问是最危险的Web漏洞之一,因为我们将 ...

  9. java中的io系统详解

    相关读书笔记.心得文章列表 Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字 ...

  10. css 如何“画”一个抽奖转盘

    主要描述的是如何运用 css 绘制一个抽奖转盘,并运用原生 js 实现转盘抽奖效果. 先来张效果图: 布局 一般来说,转盘一般有四个部分组成:外层闪烁的灯.内层旋转的圆盘.圆盘上的中奖结果.指针. 所 ...