从零开始编写属于我的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设计模式系列文章>.卡奴达摩的<设计模式>还有其他一些零散 ...
随机推荐
- 思维导图FreeMind
什么是MindMap? MindMap(被译成思维导图或心智图)是一种思维工具,由英国的记忆之父托尼-博赞发明. MindMap是一种新的思维模式,它将左脑的逻辑.顺序.条例.文字.数字,以及右脑的图 ...
- 我的面板我做主 -- 淘宝UWP中自定义Panel的实现
在Windows10 UWP开发平台上内置的XMAL布局面板包括RelativePanel.StackPanel.Grid.VariableSizedWrapGrid 和 Canvas.在开发淘宝UW ...
- Python黑帽编程2.6 模块
Python黑帽编程2.6 模块 我们已经学习了如何在你的程序中定义一次函数而重用代码.如果你想要在其他程序中重用很多函数,那么你该如何编写程序呢?你可能已经猜到了,答案是使用模块.模块基本上就是一个 ...
- 细说 Data URI
Data URL 早在 1995 年就被提出,那个时候有很多个版本的 Data URL Schema 定义陆续出现在 VRML 之中,随后不久,其中的一个版本被提上了议案——将它做个一个嵌入式的资源放 ...
- 干掉Unity3D
我为什么想干掉Unity3D? 这个问题容我不答,每个做技术的人总有一些完美主义. 你使用u3d的过程中是不是痛并快乐着呢. 就从两个国内具有相当普遍性的痛点说起. il2cpp,unity作出了这个 ...
- ubuntu升级内核后vmware-player启动失败
在虚拟机软件中,vmware player是对硬件支持很好的,通过它可以很方便的使用网银.单片机开发等等工作.但是最近ubuntu每次升级内核后,vmware都会启动失败,提示:Before you ...
- Spark使用实例
1.介绍 Spark是基于Hadoop的大数据处理框架,相比较MapReduce,Spark对数据的处理是在本地内存中进行,中间数据不需要落地,因此速度有很大的提升.而MapReduce在map阶段和 ...
- VB6.0中,DTPicker日期、时间控件不允许为空时,采用文本框与日期、时间控件相互替换赋值(解决方案)
VB6.0中,日期.时间控件不允许为空时,采用文本框与日期.时间控件相互替换赋值,或许是一个不错的选择. 实现效果如下图: 文本框txtStopTime1 时间框DTStopTime1(DTPicke ...
- easyui datagrid cell title换行
" " title="' +row.TaskName + "
- 准备 KVM 实验环境 - 每天5分钟玩转 OpenStack(3)
KVM 是 OpenStack 使用最广泛的 Hypervisor,本节介绍如何搭建 KVM 实验环境 安装 KVM 上一节说了,KVM 是 2 型虚拟化,是运行在操作系统之上的,所以我们先要装一个 ...