可扩展编程MEF学习笔记
2021-05-07 18:51 .net小跟班(杜) 阅读(107) 评论(0) 编辑 收藏 举报MEF,全称Managed Extensibility Framework(托管可扩展框架)
对MEF有这样一段说明:
Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。
主要原理是C#的依赖注入原则
代码层级关系
新建Bootstrapper类继承至BootstrapperBase:
public class Bootstrapper:BootstrapperBase { private CompositionContainer m_container; public Bootstrapper() { Initialize(); } protected override void OnStartup(object sender, StartupEventArgs e) { DisplayRootViewFor<PopupWindowViewModel>(); } protected override void Configure() { m_container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x=>new AssemblyCatalog(x)))); var batch = new CompositionBatch(); batch.AddExportedValue<IWindowManager>(new WindowManager());//新建一个窗口管理器添加到IOC中 batch.AddExportedValue<IEventAggregator>(new EventAggregator());//弱事件添加 batch.AddExportedValue(m_container); m_container.Compose(batch); } /// <summary> /// IOC容器获取实例的方法 /// </summary> /// <param name="service"></param> /// <param name="key"></param> /// <returns></returns> protected override object GetInstance(Type service, string key) { string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key; var exports = m_container.GetExportedValues<object>(contract); var exportList = exports.ToList();//避免直接用exports时 调用2次IEnumerable操作 if (exportList.Any()) { return exportList.First(); } throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract)); } /// <summary> /// IOC容器获取实例的方法 /// </summary> /// <param name="service"></param> /// <returns></returns> protected override IEnumerable<object> GetAllInstances(Type service) { return m_container.GetExportedValues<object>(AttributedModelServices.GetContractName(service)); } /// <summary> /// IOC容器注入实例的方法 /// </summary> /// <param name="instance"></param> protected override void BuildUp(object instance) { m_container.SatisfyImportsOnce(instance); } /// <summary> /// 设置加载到AssemblySource中的程序集列表 /// </summary> /// <returns></returns> protected override IEnumerable<Assembly> SelectAssemblies() { List<Assembly> list = base.SelectAssemblies().ToList(); list.AddRange(new List<Assembly> { Assembly.Load("MyDll") }); return list; } protected override void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { e.Handled = true; } }
VM继承至Screen
[Export(typeof(PopupWindowViewModel))] public class PopupWindowViewModel:Screen { public IWindowManager _WindowManager { get; set; } [ImportingConstructor]//必须加入这个,这是因为用MEF在创建ViewModel实例时,有[ImportingConstructor]标记的构造函数的参数会自动使用容器内相应的export对象 public PopupWindowViewModel(IWindowManager windowManager) { this._WindowManager = windowManager; } protected override void OnInitialize() { _WindowManager.ShowDialog(new MainViewModel()); } public void PopupForm() { _WindowManager.ShowWindow(new EditUserViewModel(_WindowManager)); } }
实现效果
典型的MEF组合过程
(1)创建组件目录(如AssemblyCatalog)
(2)创建组合容器CompositionContainer,组件容器通过组件目录搜索组件的定义
(3)创建一个组件
(4)从组件容器获取其它组件功能的定义,然后执行匹配组合