WPF使用MEF插件开发打造自己的工具箱
最近闲来无事,想着搞点事情来着,想搞一个工具箱程序,又想着自由灵活点,于是就选用了MEF.这玩意适用于小的项目,可以方便的做出一个插件开发系统.
顺道又把之前做的截图工具也加入进来了,基础框架弄好之后,再开发别的插件,就是依样画葫芦喽,
现在还没做什么,只是开发了几个插件嘿嘿
先来看看效果吧.
刚开始做,还没有做几个插件.后续几个文章中,我会把项目源码带出来,大家学会了之后,可以一起来开发,打造一个牛逼哄哄的插件系统喽.
后续打算把它做成从服务器上检索插件的形式,找到想要的插件,就点击下载直接使用.嘿嘿.一步一步来吧.
下面我先介绍一下MEF
MEF简介
MEF可以方便的在c#程序中实现插件式开发。通过接口暴露公开方法,插件内继承接口的类可以通过[export]特性公开出去,宿主程序通过[import]特性建立接口类型的属性,启用插件方法.插件可以和主程序不在一个程序集,实现插件完全独立的开发.
使用MEF主要由4个步骤完成
1、定义插件插口
2、公开接口的实现类.(使用[export]特性)
3、通过[import]特性调用插件
4、加载到主程序中
话不多说,直接上代码,懂的人自然懂.不懂的建议先学一下c#基础哦
1.新建DLL工程.创建一个IPlugin 接口.用于对外公开
项目目录如下:
定义插件接口,实现插件必要的属性.代码如下:
namespace Plugin.Base
{public interface IPlugin{//主程序调用此方法,启动插件void Startup(object args = null);//主程序调用此方法,退出插件void Close(object args = null);//插件名,用于主程序中获取并显示string PluginName { get; }//插件唯一Key,用于区分插件,(后期做下载更新插件的时候会用到,现在没啥用)Guid PluginKey { get; }//插件的图标,用于主程序中获取并显示ImageSource PluginIcon { get; }//插件的启动Command,用于Wpf程序中绑定使用System.Windows.Input.ICommand StartupCommand { get; }//插件的关闭Command,用于Wpf程序中绑定使用System.Windows.Input.ICommand CloseCommand { get; }//插件的描述,用于主程序中获取并显示string PluginDescription { get; }//忘记了为啥,当时写的时候,加上了这个属性,现在想不起来了,算了,先放这吧,不用管它bool LoadSucceed { get; set; }//是否支持自启动.想着后期工具箱要做开机自启的.工具箱启动后,又能自动启动这些设置了自启的插件bool SupportAutoStartup { get; set; }//插件被加载手,主程序调用此方法,初始化插件void Initialize();}
}
2.主程序创建加载插件的PluginLoader类
本节主要关注这个PlginLoader.cs.其它文件请自动忽略
代码如下,代码解释,我都写在注释里了.各位请看:
using Plugin.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using ViewModel.Base;
namespace Tools
{public class PluginLoader{//些特性表示加载实现了Iplugin接口的类[ImportMany(typeof(IPlugin))]private IEnumerable<IPlugin> Plugins { get; set; }public PluginLoader(){//这个下载插件的的功能,还没有做好,先把事件写了,放在这,先不用管,后面会再讲解Global.OnPluginDownLoadSucceed += OnPluginDownLoadSucceed;}//插件下载成功事件,下载后加载插件,按照插件的PluginKey加载(不懂的看上面的Iplugin接口)private void OnPluginDownLoadSucceed(string guid){try{AggregateCatalog catalog = new AggregateCatalog();//设置插件目录为程序目录,插件名称为Tools.Plugin.{guid}.dll//这是我们的定义的规定,后面开发的插件,dll名字都要是这样的//没有规矩不成方圆catalog.Catalogs.Add(new DirectoryCatalog(".", $"Tools.Plugin.{guid}.dll"));//加载插件using (CompositionContainer container = new CompositionContainer(catalog)){container.ComposeParts(this);foreach (var plugin in Plugins){//初始化插件plugin.Initialize();//存到主程序中,后面调用使用Global.Plugins.Add(plugin);}}//我们添加的更多插件,这是一个默认插件,想着搞个官网装下B呢嘿嘿var more = Global.Plugins.FirstOrDefault(r => r.PluginKey == Global.MorePluginKey);if (more != null){Global.Plugins.Remove(more);Global.Plugins.Add(more);}}catch (Exception ex){Log.File(ex, "加载插件异常");}}//主程序启动后,调用此方法,可加载目录中所有插件public void Load(){try{AggregateCatalog catalog = new AggregateCatalog();//设置插件目录为程序目录,插件名称为Tools.Plugin.*.dllcatalog.Catalogs.Add(new DirectoryCatalog(".", "Tools.Plugin.*"));using (CompositionContainer container = new CompositionContainer(catalog)){container.ComposeParts(this);foreach (var plugin in Plugins){plugin.Initialize();Global.Plugins.Add(plugin);}}var more = Global.Plugins.FirstOrDefault(r => r.PluginKey == Global.MorePluginKey);if (more != null){Global.Plugins.Remove(more);Global.Plugins.Add(more);}}catch (Exception ex){Log.File(ex, "加载插件异常");}}}
}
3.主程序有了,接口有了.那么,来搞个插件试试吧
新建Dll项目,命名为:Tools.Plugin.More (和我们上面 写的加载的插件格式对应)
再写个Plugin类,实现IPlugin接口
目录如下 :
主要看Plugin.cs和引用的Plugin.Base项目.其它请自动忽略
Plugin.cs代码如下:
using Plugin.Base;
using System;
using System.ComponentModel.Composition;
using System.Windows.Input;
using System.Windows.Media;
using ViewModel.Base;namespace Tools.Plugin.More
{//务必使用此特性,向外公开IPlugin类型//实现IPlugin[Export(typeof(IPlugin))]public class Plugin : IPlugin{public string PluginName => "更多精彩";public Guid PluginKey => new Guid("be8ff5b2-733e-4b76-a9c2-f7ec57ee6d18");//这里提供一个图片,作为主程序显示插件的图标用,这个还要转一下类型,唉,当时设计失误,算了,不想改了public ImageSource PluginIcon => ImageHelper.BitmapToBitmapImage(Properties.Resources.More64);public string PluginDescription => "打开官网查看更多";public ICommand StartupCommand { get; private set; }public ICommand CloseCommand { get; private set; }public bool LoadSucceed{get => true;set{throw new NotSupportedException($"本插件不支持修改此属性:{nameof(LoadSucceed)}");}}public bool SupportAutoStartup { get => false; set { } }public void Initialize(){StartupCommand = new RelayParameterizedCommand((args) => Startup(args));CloseCommand = new RelayParameterizedCommand((args) => Close(args));}public void Startup(object args = null){System.Diagnostics.Process.Start("https://www.gggcloud.top");}public void Close(object args = null){}}
}
好了,把这个插件项目,和主程序编译到一个目录下,启动主程序时,调用PluginLoader.Load方法,就可以加载这个插件了.至于加载后怎么处理,等下一篇文章再说吧,这个文章字太多啦,打字打的累手...
好吧,就先写到这了,下期再会
手机上看代码不方便,建议使用电脑版微信,用浏览器打开看哦
获取更多知识,公众号:dotNET编程大全,扫码关注!
需加微信交流群的,请加小编微信号z438679770,切记备注 加群,小编将会第一时间邀请你进群!
每日分享不易,"在看"就是鼓励!
WPF使用MEF插件开发打造自己的工具箱相关推荐
- 【WPF】用CustomControl打造WPF版的Marquee
控件代码已经更新,支持上下左右四个方向.VS2010工程 /Files/RMay/WPF_Marquee/WpfMarquee.zip 我们知道在html中有一个marquee标签,可以很方便的实现文 ...
- Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
现在如果想打造一款专业的App,UI的设计和操作的简便性相当重要.UI设计可以借助Photoshop或者AI等设计工具,之前了解到WPF设计工具Expression Blend可以直接导入PSD文件或 ...
- wpf之MEF+MVVM结合
最近想写一个基于wpf的客户端,想采用MEF插件的模式开发各个界面插件.界面的插件采用MVVM框架搭建. 先说一下MVVM,这里我有一点非常疑惑,M表示module,V表示view VM表示界面的数 ...
- 在U盘打造个性化PE工具箱+KALI(Persistence)+存储的工作站
基本工具: kali-linux-2018.2-amd64 原版镜像:https://www.kali.org/downloads Win32DiskImager yunfile 下载较慢,建议自行百 ...
- (KALI)在U盘打造个性化PE工具箱+KALI(Persistence)+存储的工作站
手上有个64G的U盘,单做PE工具箱或者单做Kali系统都会比较浪费,所以想到了实现PE工具箱+kali系统(带persistence保存数据的功能)+存储三合一,试过各种方法,失败了很多次,总结了很 ...
- FFmpeg+Python打造命令行工具箱
目录 总操作模式的设计 一次可以处理多个文件. 一个例子 多文件处理的技巧 参数设计 输出路径 工具一.Gif 转换器 方法来源 效果参考 实际指令 代码以及使用 工具二.画面裁切(crop) 参数 ...
- Android手机添加BusyBox超级终端打造linux工具箱
在Android下可以添加BusyBox&超级终端打造一个linux工具箱环境 可以执行很多linux下的命令方便调试.测试应用 1.手机需要Root 2.现在安装BusyBox 与 超级终端 ...
- WPF+WCF一步一步打造音频聊天室(一):概述
前几天在老徐的MSN群中聊WCF.我突然想到了用WPF和WCF来打造音频聊天室这么一个轮子.其实是这样的,我在的公司是两岸三地合作开发的.两岸是指大陆和台湾,三地是指深圳.台北.高雄.由于公司很小,所 ...
- WPF界面控件Telerik UI for WPF新手入门教程 - 如何添加telerik控件
本教程将介绍执行哪些步骤才能在应用程序中添加Telerik UI for WPF控件. 有两种方法可以做到这一点 - 第一种是为 VisualStudio 安装 Progress Telerik WP ...
最新文章
- 防火墙产品原理与应用:防火墙产品的技术及实现关于IPV6【寒假】
- 传统软件的云计算之路
- VC 使用SetCheck(TRUE)函数的注意事项
- linux搭建环境经验,经验总结54--搭建linux虚拟机环境
- 算法—1,简单说说最常见的冒泡排序(Bubble Sort)
- Nginx在多层代理下获取真实客户端IP地址
- 二维有限元方程matlab,有限元法求解二维Poisson方程的MATLAB实现
- 解决问题E: 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用) E: 无法锁定管理目录,
- Python callable 函数 - Python零基础入门教程
- mybatis 原理_Mybatis的工作原理
- 5分钟轻松学Python:4行代码写一个爬虫
- ES6学习笔记(二)—— 通过ES6 Module看import和require区别
- EDIUS如何缩短时间线长度
- 【图解算法】最小生成树
- 基于R语言做层次聚类分析
- 基于 esp-idf 的 UART 应用例程解读
- AutoJs学习-2048小游戏自动化
- LL(1)预测分析程序
- AI大模型加持,生成式搜索来了!
- 基于遗传算法的大规模工程优化设计方法初探
热门文章
- GIS中的坐标系问题
- USB转ESP8266 01 WIFI串口模块 电脑无线通信单片机转接板烧录固件 AirKiss SmartConfig 智能配网
- odoo本地文档功能开发记录
- 网页设计至少要掌握哪些技能
- 电动汽车,绝缘检测方法
- 公司股权分配协议 (2)
- 会计信息系统问答题计算机网络,2020年4月自考《会计信息系统》复习题及答案(7)...
- 2021谷歌员工工资
- 计算机天文应用与计算专业,专业介绍-中国科学院国家天文台南京天文光学技术研究所...
- 换用国内apt源解决树莓派安装ubuntu后apt-get速度慢的问题