最近闲来无事,想着搞点事情来着,想搞一个工具箱程序,又想着自由灵活点,于是就选用了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插件开发打造自己的工具箱相关推荐

  1. 【WPF】用CustomControl打造WPF版的Marquee

    控件代码已经更新,支持上下左右四个方向.VS2010工程 /Files/RMay/WPF_Marquee/WpfMarquee.zip 我们知道在html中有一个marquee标签,可以很方便的实现文 ...

  2. Photoshop和WPF双剑配合,打造炫酷个性的进度条控件

    现在如果想打造一款专业的App,UI的设计和操作的简便性相当重要.UI设计可以借助Photoshop或者AI等设计工具,之前了解到WPF设计工具Expression Blend可以直接导入PSD文件或 ...

  3. wpf之MEF+MVVM结合

    最近想写一个基于wpf的客户端,想采用MEF插件的模式开发各个界面插件.界面的插件采用MVVM框架搭建. 先说一下MVVM,这里我有一点非常疑惑,M表示module,V表示view  VM表示界面的数 ...

  4. 在U盘打造个性化PE工具箱+KALI(Persistence)+存储的工作站

    基本工具: kali-linux-2018.2-amd64 原版镜像:https://www.kali.org/downloads Win32DiskImager yunfile 下载较慢,建议自行百 ...

  5. (KALI)在U盘打造个性化PE工具箱+KALI(Persistence)+存储的工作站

    手上有个64G的U盘,单做PE工具箱或者单做Kali系统都会比较浪费,所以想到了实现PE工具箱+kali系统(带persistence保存数据的功能)+存储三合一,试过各种方法,失败了很多次,总结了很 ...

  6. FFmpeg+Python打造命令行工具箱

    目录 总操作模式的设计 一次可以处理多个文件. 一个例子 多文件处理的技巧 参数设计 输出路径 工具一.Gif 转换器 方法来源 效果参考 实际指令 代码以及使用 工具二.画面裁切(crop) 参数 ...

  7. Android手机添加BusyBox超级终端打造linux工具箱

    在Android下可以添加BusyBox&超级终端打造一个linux工具箱环境 可以执行很多linux下的命令方便调试.测试应用 1.手机需要Root 2.现在安装BusyBox 与 超级终端 ...

  8. WPF+WCF一步一步打造音频聊天室(一):概述

    前几天在老徐的MSN群中聊WCF.我突然想到了用WPF和WCF来打造音频聊天室这么一个轮子.其实是这样的,我在的公司是两岸三地合作开发的.两岸是指大陆和台湾,三地是指深圳.台北.高雄.由于公司很小,所 ...

  9. WPF界面控件Telerik UI for WPF新手入门教程 - 如何添加telerik控件

    本教程将介绍执行哪些步骤才能在应用程序中添加Telerik UI for WPF控件. 有两种方法可以做到这一点 - 第一种是为 VisualStudio 安装 Progress Telerik WP ...

最新文章

  1. 防火墙产品原理与应用:防火墙产品的技术及实现关于IPV6【寒假】
  2. 传统软件的云计算之路
  3. VC 使用SetCheck(TRUE)函数的注意事项
  4. linux搭建环境经验,经验总结54--搭建linux虚拟机环境
  5. 算法—1,简单说说最常见的冒泡排序(Bubble Sort)
  6. Nginx在多层代理下获取真实客户端IP地址
  7. 二维有限元方程matlab,有限元法求解二维Poisson方程的MATLAB实现
  8. 解决问题E: 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用) E: 无法锁定管理目录,
  9. Python callable 函数 - Python零基础入门教程
  10. mybatis 原理_Mybatis的工作原理
  11. 5分钟轻松学Python:4行代码写一个爬虫
  12. ES6学习笔记(二)—— 通过ES6 Module看import和require区别
  13. EDIUS如何缩短时间线长度
  14. 【图解算法】最小生成树
  15. 基于R语言做层次聚类分析
  16. 基于 esp-idf 的 UART 应用例程解读
  17. AutoJs学习-2048小游戏自动化
  18. LL(1)预测分析程序
  19. AI大模型加持,生成式搜索来了!
  20. 基于遗传算法的大规模工程优化设计方法初探

热门文章

  1. GIS中的坐标系问题
  2. USB转ESP8266 01 WIFI串口模块 电脑无线通信单片机转接板烧录固件 AirKiss SmartConfig 智能配网
  3. odoo本地文档功能开发记录
  4. 网页设计至少要掌握哪些技能
  5. 电动汽车,绝缘检测方法
  6. 公司股权分配协议 (2)
  7. 会计信息系统问答题计算机网络,2020年4月自考《会计信息系统》复习题及答案(7)...
  8. 2021谷歌员工工资
  9. 计算机天文应用与计算专业,专业介绍-中国科学院国家天文台南京天文光学技术研究所...
  10. 换用国内apt源解决树莓派安装ubuntu后apt-get速度慢的问题