勇哥注:
MEF无论是在.net framework还是在.net core中都是可以使用的。
.net framework下的包叫 System.ComponentModel.Composition
.net core下的包叫System.Composition

微软的MEF全称是Managed Extensibility Framework,也被称为托管可扩展框架。 它是微软.NET框架下为提高应用和组件复用程度而推出的一种技术。 MEF是一个用于创建可扩展的轻型应用程序的库,它提供了一系列特性, 包括依赖注入(DI)以及Duck Typing等
这东西的应用包括:
插件化应用程序: MEF允许应用程序在运行时动态地加载和卸载插件,从而实现功能的扩展和定制。 插件开发人员可以独立开发、测试和部署插件,而无需修改主应用程序的代码。 主应用程序可以通过MEF的接口发现和加载插件,实现功能的动态扩展。 模块化应用程序: 通过使用MEF,开发人员可以将应用程序拆分成多个模块,每个模块都可以独立开发、测试和部署。 这些模块可以在运行时动态地合并到主应用程序中,实现功能的模块化组合。 模块的依赖关系可以通过MEF的依赖注入机制进行管理,提高代码的可维护性和可测试性。 可扩展的框架: MEF可以用于构建可扩展的框架,使得其他开发人员可以通过编写插件来扩展框架的功能。 框架开发人员可以定义扩展点或接口,允许插件实现这些接口以提供额外的功能。 插件开发人员可以独立开发插件,并通过MEF将其集成到框架中,实现功能的扩展和定制。 边缘节点管理和容器应用管理: 在云计算和边缘计算领域,MEF可以用于管理边缘节点和容器应用。 通过将集群中的边缘节点纳管入MEF系统中,可以实现对边缘节点信息的统一管理, 包括节点的增、删、改、查等功能。 对于容器应用,MEF可以管理用户的容器应用镜像, 涉及容器应用的增、删、改、查等全生命周期管理功能。
(一)基本应用
控制台源码:
(1)结合图2的工程结构看,控制台程序ConsoleApp1并没有直接引用Business.Service。
它完全是用的抽象(接口ITestServiceA 和ITestServiceB),没有用到现实类。
这样就达到了模块之间解藕的效果。
(2)MEF是在模块的类上用专用特性进行标记,然后应用者可以在指定目录下发现这些打了标记的dll,
然后可以通过GetExport() 等方法调用这些函数。
(3)注意CompositionContainer用到的路径只是控制台程序的bin目录下面,因此你得把Service这个dll项目的生成路径改为控制台程序的bin目录。
每次dll修改后,你得重新生成整个方案。
using Business.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
CompositionContainer container = null; //声明容器
AggregateCatalog catelog = new AggregateCatalog();
container = new CompositionContainer(new DirectoryCatalog($"{AppDomain.CurrentDomain.BaseDirectory}"));
Lazy <ITestServiceA> ta = container.GetExport<ITestServiceA>();
ITestServiceA testServiceA = ta.Value;
testServiceA.Show();
ITestServiceA testServiceA2 = container.GetExportedValue<ITestServiceA>();
testServiceA2.Show();
Lazy<ITestServiceB> tb = container.GetExport<ITestServiceB>();
ITestServiceB testServiceB = tb.Value;
testServiceB.Show();
ITestServiceB testServiceB2 = container.GetExportedValue<ITestServiceB>();
testServiceB2.Show();
Console.ReadKey();
}
}
}实现类TestServiceA 的源码:
using Business.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Business.Service
{
[Export(typeof(ITestServiceA))]
public class TestServiceA : ITestServiceA
{
public TestServiceA()
{
Console.WriteLine($"{this.GetType().FullName} 被构造\n");
}
public virtual string Show()
{
Console.WriteLine("TestServiceA run...\n");
return DateTime.Now.ToString();
}
}
}
(图1)

(图2)
源码下载:
勇哥用的是VS2017+ .net framework4.6 + System.ComponentModel.Composition 6.0
注意现在是2024年5月,System.ComponentModel.Composition包最高已经到了9.0预览版了,但是只有6.0及以下版本,才支持.net framework4.6
链接:https://pan.baidu.com/s/1OiVwPjgPmedywxYl5MMMLA
提取码:5s0k
--来自百度网盘超级会员V6勇哥的分享
(二)构造函数注入
勇哥把TestServiceB增加一个构造函数。
把它标记 [ImportingConstructor],并把构造参数标记[Import]
[Export(typeof(ITestServiceB))]
class TestServiceB : ITestServiceB
{
private ITestServiceA testA;
[ImportingConstructor]
public TestServiceB([Import]ITestServiceA data)
{
Console.WriteLine($"{data.GetType().FullName}被di注入");
testA = data;
}
public void Show()
{
Console.WriteLine("ITestServiceB run...\n");
}
}然后在控制台端下面划线处代码执行时,框架会自动注入一个新创建的ITestServiceA的实例。

见下面输出:

链接:https://pan.baidu.com/s/1fdqXu6pzTGIdAr69aGtiVA
提取码:zra3
--来自百度网盘超级会员V6勇哥的分享
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路



















