勇哥注:
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
版权声明:本文为博主原创文章,转载请附上博文链接!

