从零开始编写属于我的CMS:(六)插件
二三四五还没写,先写六吧(有道友说想看看插件部分)。
这里是一 从零开始编写属于我的CMS:(一)前言
一,首先预定义接口
新建类库,WangCms.PluginInterface
新建两个类,一个实体Models.cs,一个接口IPlugin.cs
Models是插件所用到的实体集合类;IPlugin是为第三方预定义接口,所有插件必须实现该接口。
实体Models代码如下
namespace WangCms.PluginInterface { public class PluginInfo { /// <summary> /// Code /// </summary> public string Code { get; set; } /// <summary> /// 插件名称 /// </summary> public string Name { get; set; } /// <summary> /// 作者 /// </summary> public string Author { get; set; } /// <summary> /// 插件版本 /// </summary> public string Version { get; set; } /// <summary> /// 适用cms版本 /// </summary> public string ApplyVersion { get; set; } /// <summary> /// 描述信息 /// </summary> public string Description { get; set; } //附加信息 public string Area { get; set; } public string AdminController { get; set; } public string AdminAction { get; set; } public string AdminQueryString { get; set; } } public class ResultOptin<T> { public bool State { get; set; } public string Msg { get; set; } public T Result { get; set; } } }
接口IPlufin代码如下
namespace WangCms.PluginInterface { public interface IPlugin { /// <summary> /// 插件注册 /// </summary> /// <returns></returns> ResultOptin<PluginInfo> Register(); /// <summary> /// 插件安装 /// </summary> /// <param name="model"></param> /// <returns></returns> ResultOptin<string> Install(); /// <summary> /// 插件卸载 /// </summary> /// <returns></returns> ResultOptin<string> Uninstall(); } }
二,留言插件
新建一个插件项目(类库),WangCms.Plugin.LiuYan
然后添加相关引用(MVC、WangCms.PluginInterface)等。
首先实现插件接口,新建PluginRegister.cs继承IPlugin,主要为了实现插件的注册、安装以及卸载功能的实现。
PluginRegister代码如下
namespace WangCms.Plugin.LiuYan { public class PluginRegister : IPlugin { #region 实现接口 public ResultOptin<PluginInfo> Register() { ResultOptin<PluginInfo> result = new ResultOptin<PluginInfo>(); try { PluginInfo model = new PluginInfo(); //后台管理入口 model.Area = "LiuYan"; model.AdminController = "LiuYanAdmin"; model.AdminAction = "Index"; model.AdminQueryString = null; //插件基本信息 model.Code = "48a3619327c64a9aa68645007037b451"; model.Name = "在线留言"; model.Author = "千年"; model.Version = "1.0.0"; model.ApplyVersion = "1.0.0"; model.Description = ""; //状态 特别重要 result.State = true; result.Result = model; } catch(Exception ex) { result.State = false; result.Msg = ex.Message; } return result; } public ResultOptin<string> Install() { ResultOptin<string> result = new ResultOptin<string>(); try { //安装插件 //比如执行sql(创建表,插入数据等),创建目录,创建文件等 string sql = @"create table LiuYan( Id varchar(50) primary key, Title varchar(50), Name varchar(50), Contact varchar(50), Content text );"; LiuYanService.Instance.Excute(sql); result.State = true; } catch(Exception ex) { result.State = false; result.Msg = ex.Message; } return result; } public ResultOptin<string> Uninstall() { ResultOptin<string> result = new ResultOptin<string>(); try { //卸载插件 //比如执行sql(删除表,删除数据等),删除目录,删除文件等 string sql = @"drop table LiuYan;"; LiuYanService.Instance.Excute(sql); result.State = true; } catch(Exception ex) { result.State = false; result.Msg = ex.Message; } return result; } #endregion } }
其实,只要实现了接口插件就算完成了,只是该插件还不具备任何实用功能,根据插件名字我想大家知道这个是干嘛的了吧,这就是在线留言的插件,下面就是很简单的留言业务逻辑以及功能的实现了。
插件区域,就是MVC的区域,我们用不同区域来区分和管理插件。
MVC区域,不熟悉的同学可以在园子里搜搜相关文章。
在区域里面可以建Controller和View,还有比较重要的就是区域注册,就是区域的路由吧。
LiuYanAreaRegistration.cs
namespace WangCms.Plugin.LiuYan { public class LiuYanAreaRegistration : AreaRegistration { public override string AreaName { get { return "LiuYan"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "LiuYan_default", "LiuYan/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional }, new string[] { "WangCms.Plugin.LiuYan.Controllers" } ); } } }
然后,就是功能实现了,这部分就略过吧。
在线留言后台管理,新建一个控制器AdminController.cs以及相应的视图。
在线留言前台功能,新建一个控制器PageController.cs以及相应的视图。
三,插件使用
主项目如何使用插件呢?
首先将编译好的插件,上传至主项目下,结构如图。
视图文件和插件时路径一致,WangCms.Plugin.LiuYan.dll上传至主项目bin下。
3.1 获取插件列表
private List<Plugin> GetPluginList() { List<Plugin> list = new List<Plugin>(); string path = Server.MapPath("/bin/"); FileInfo[] files = (new DirectoryInfo(path)).GetFiles("*.dll"); foreach (var item in files) { try { if (!item.Name.StartsWith("WangCms.Plugin.")) continue; Plugin model = new Plugin(); Assembly ass = Assembly.LoadFile(item.FullName); Type tp = ass.GetType(item.Name.Replace(".dll", "") + "." + "PluginRegister"); //获取类名,必须 命名空间+类名 Object obj = Activator.CreateInstance(tp); //建立实例 MethodInfo meth = tp.GetMethod("Register"); //获取方法 object t = meth.Invoke(obj, null); //Invoke调用方法 PluginInterface.ResultOptin<PluginInterface.PluginInfo> result = (PluginInterface.ResultOptin<PluginInterface.PluginInfo>)t; if (result.State)//插件注册成功 { ToPlugin(result.Result, ref model); model.Type = tp; list.Add(model); } } catch { } } return list; }
这里有一个插件类转换的方法。
private void ToPlugin(PluginInterface.PluginInfo t, ref Plugin p) { if (t != null) { p.Code = t.Code; p.Name = t.Name; p.Author = t.Author; p.Version = t.Version; p.ApplyVersion = t.ApplyVersion; p.Description = t.Description; p.AdminController = t.AdminController; p.AdminAction = t.AdminAction; p.AdminQueryString = t.AdminQueryString; } }
3.2 安装插件
public ActionResult plugin_install(string code) { var list = GetPluginList(); var o = list.FirstOrDefault(op => op.Code == code); if (o != null) { //执行安装方法 Object obj = Activator.CreateInstance(o.Type); //建立实例 MethodInfo meth = o.Type.GetMethod("Install"); //获取方法 object t = meth.Invoke(obj, null); //Invoke调用方法 PluginInterface.ResultOptin<string> result = (PluginInterface.ResultOptin<string>)t; if (result.State) { //记录数据 PluginService.Instance.UpdateOrInsert(o); } else { return Content(result.Msg); } } return RedirectToAction("plugin_list"); }
3.3 卸载插件
public ActionResult plugin_uninstall(string code) { var list = GetPluginList(); var o = list.FirstOrDefault(op => op.Code == code); if (o != null) { //执行安装方法 Object obj = Activator.CreateInstance(o.Type); //建立实例 MethodInfo meth = o.Type.GetMethod("Uninstall"); //获取方法 object t = meth.Invoke(obj, null); //Invoke调用方法 PluginInterface.ResultOptin<string> result = (PluginInterface.ResultOptin<string>)t; if (result.State) { //删除数据 PluginService.Instance.DeleteByCode(o.Code); } else { return Content(result.Msg); } } return RedirectToAction("plugin_list"); }
插件源码下载
从零开始编写属于我的CMS:(六)插件的更多相关文章
- 从零开始编写属于我的CMS:(一)前言
一,项目背景 记得大学毕业课题,我就是选择做个CMS,不过当时虽然做了个,不过感觉不是很好,所以现在又重做了,顺便发上来供大家讨论的.虽然CMS不是什么特别的项目,但是还是想从一个普通项目学到更多的东 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用
标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1171 ...
- 从零开始编写一个vue插件
title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...
- 从零开始编写IntelliJ IDEA插件
写Java代码的时候,经常会涉及到重复性的操作,这个时候就会想要是有这样一个插件就好了,如果是大家都会遇到的场景,IDE或许已经提供了,再不然也有可能有人编写了相关的插件.要是这个操作是你们的编码环境 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用ApplicationPart动态加载控制器和视图
标题:从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 作者:Lamond Lu 地址:http://www.cnblogs ...
- 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案
标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun ...
- 从零开始编写自己的C#框架(1)——前言
记得十五年前自学编程时,拿着C语言厚厚的书,想要上机都不知道要用什么编译器来执行书中的例子.十二年前在大学自学ASP时,由于身边没有一位同学和朋友学习这种语言,也只能整天混在图收馆里拼命的啃书.而再后 ...
- 从零开始编写自己的C#框架(20)——框架异常处理及日志记录
最近很忙,杂事也多,所以开发本框架也是断断续续的,终于在前两天将前面设定的功能都基本完成了,剩下一些小功能遗漏的以后发现再补上.接下来的章节主要都是讲解在本框架的基础上进行开发的小巧. 本框架主要有四 ...
- 从零开始编写自己的C#框架(11)——创建解决方案
这段时间一直在充电,拜读了园子中大神们的博文(wayfarer的<设计之道>.TerryLee的<.NET设计模式系列文章>.卡奴达摩的<设计模式>还有其他一些零散 ...
随机推荐
- .Net开发笔记(二十)创建一个需要授权的第三方组件
在使用需要授权的软件时,注册付费的目标是软件的使用者,我们开发人员平时用到的一些第三方组件也是需要授权付费的,也就是说,付费者是开发人员,并不是系统(使用了该第三方组件)的最终使用者. 以上两者的区别 ...
- 纯命令行的编辑利器:用好 awk 与 sed
awk 的基本语法 awk 是模式查找与处理语言,是文本处理的利器.使用 awk 可以只用一条简单的命令完成复杂的文本数据处理. awk 命令的基本结构为: awk '模式 {处理}' 文件 比如,打 ...
- HTML5中类jQuery选择器querySelector的使用
简介 HTML5向Web API新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的 ...
- WCF Security基本概念(转载)
WCF Security 主要包括 "Transfer Security"."Access Control"."Auditing" 几个部分 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (10) -----第二章 实体数据建模基础之两实体间Is-a和Has-a关系建模、嵌入值映射
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-11 两实体间Is-a和Has-a关系建模 问题 你有两张有Is-a和Has-a ...
- 循序渐进,了解Hive是什么!
一直想抽个时间整理下最近的所学,断断续续接触hive也有半个多月了,大体上了解了很多Hive相关的知识.那么,一般对陌生事物的认知都会经历下面几个阶段: 为什么会出现?解决了什么问题? 如何搭建?如何 ...
- iOS-语言本地化
在使用本地化语言之前,来看看本地化语言文件内容的结构(这里我以Chinese为例):"Cancel"="取消";"OK"="确定& ...
- easyui中方向键、tab键、回车键
1.html中 function changeTab(event, i) { var keyCode = event.keyCode; var inputs = jQuery("#table ...
- Android自定义属性
上一篇讲解了Android自定义View,这篇来讲解一下Android自定义属性的使用,让你get新技能.希望我的分享能帮助到大家. 做Android布局是件很享受的事,这得益于他良好的xml方式.使 ...
- MySQL主从复制中断,报“Error on master: message (format)='Cannot delete or update a parent row: a foreign key constraint fails' error code=1217” 错误
前几天,发现从库挂了,具体报错信息如下: 分析思路 1. 因为我采用的是选择性复制,只针对以下几个库进行复制: card,upay,deal,monitor,collect.所以,不太可能出现对于sa ...