二三四五还没写,先写六吧(有道友说想看看插件部分)。

这里是一 从零开始编写属于我的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:(六)插件的更多相关文章

  1. 从零开始编写属于我的CMS:(一)前言

    一,项目背景 记得大学毕业课题,我就是选择做个CMS,不过当时虽然做了个,不过感觉不是很好,所以现在又重做了,顺便发上来供大家讨论的.虽然CMS不是什么特别的项目,但是还是想从一个普通项目学到更多的东 ...

  2. 从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

    标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1171 ...

  3. 从零开始编写一个vue插件

    title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...

  4. 从零开始编写IntelliJ IDEA插件

    写Java代码的时候,经常会涉及到重复性的操作,这个时候就会想要是有这样一个插件就好了,如果是大家都会遇到的场景,IDE或许已经提供了,再不然也有可能有人编写了相关的插件.要是这个操作是你们的编码环境 ...

  5. 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用ApplicationPart动态加载控制器和视图

    标题:从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 作者:Lamond Lu 地址:http://www.cnblogs ...

  6. 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案

    标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun ...

  7. 从零开始编写自己的C#框架(1)——前言

    记得十五年前自学编程时,拿着C语言厚厚的书,想要上机都不知道要用什么编译器来执行书中的例子.十二年前在大学自学ASP时,由于身边没有一位同学和朋友学习这种语言,也只能整天混在图收馆里拼命的啃书.而再后 ...

  8. 从零开始编写自己的C#框架(20)——框架异常处理及日志记录

    最近很忙,杂事也多,所以开发本框架也是断断续续的,终于在前两天将前面设定的功能都基本完成了,剩下一些小功能遗漏的以后发现再补上.接下来的章节主要都是讲解在本框架的基础上进行开发的小巧. 本框架主要有四 ...

  9. 从零开始编写自己的C#框架(11)——创建解决方案

    这段时间一直在充电,拜读了园子中大神们的博文(wayfarer的<设计之道>.TerryLee的<.NET设计模式系列文章>.卡奴达摩的<设计模式>还有其他一些零散 ...

随机推荐

  1. js中几种实用的跨域方法原理详解

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  2. 慎重管理SQL Server服务的登录(启动)账户和密码

    今天是大年初三,先跟大家拜个年,祝大家新年快乐.今天处理了一个alwaysOn问题——辅助副本因为磁盘空间不足一直显示[未同步——可疑],在日志中可以看到数据库处于挂起状态,与主副本失去同步.原以为只 ...

  3. 磁盘分区在windows和linux下的表现形式对比

    写在前面的话:磁盘分区在windows下面比较好理解,在linux下会有挂载的概念,理解起来比较难,但是可以通过与windows对比,以一种通俗的方式将他们梳理清楚. ====正文开始==== 我们的 ...

  4. Spark使用实例

    1.介绍 Spark是基于Hadoop的大数据处理框架,相比较MapReduce,Spark对数据的处理是在本地内存中进行,中间数据不需要落地,因此速度有很大的提升.而MapReduce在map阶段和 ...

  5. 入手Invicta 8926 OB潜水自动机械腕表

    前个月前就想入手一款手表了,之前在关注和学习.询问他人选哪样的表好,前些天还在看精工Seiko机械表系列,今凌晨有朋友给我推荐这款Invicta 8926系列手表,我一看便喜欢了. 在网上也是搜索了很 ...

  6. GitHub的使用记录

    前言: 该贴为笔者在使用GItHub中的一些使用注意,及Git的基本命令,会一直记录笔者在使用GitHub中可能产生的错误及解决方法(会一直更新中),待一些Git初使用者参考,如果有说明不详细或不对的 ...

  7. Java学习笔记(06)

    继承 super关键字 重写 final关键字 抽象类/abstract关键字 接口 一.继承 继承是类与类之间的继承,是一种is a 的关系(继承的满足条件) 继承的类叫子类 / 派生类,被继承的叫 ...

  8. Javascript学习记录——原生JS实现旋转木马特效

    昨天学习到了JS特效部分,然后老师讲了旋转木马特效的实现,如上图.不过只是讲了通过点击箭头实现图片的切换,对于点击图片本身以及二者联动却是没有讲解. 本着一颗追求完美的心,今天花费了一个中午终于将整个 ...

  9. android:windowSoftInputMode属性详解

    android:windowSoftInputMode activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性. 这个属性能影响两件事情: [一] ...

  10. Web APi入门之Self-Host寄宿及路由原理(二)

    前言 刚开始表面上感觉Web API内容似乎没什么,也就是返回JSON数据,事实上远非我所想,不去研究不知道,其中的水还是比较深,那又如何,一步一个脚印来学习都将迎刃而解. Self-Host 我们知 ...