好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

说说项目中的插件思想

说说项目中的插件思想

目前项目的架构基本趋势都是易扩展,易扩展主要的实现方式就是插件,在项目中所有的扩展模块都看作为是一个插件,那最为主要的就是插件与母体如何结合起来的,接下来就来讨论一下,我对于插件项目的理解和实现。同时由于本人能力有限,问题会很多,请大家批评指正。

  我认为插件就是就是一个单独的项目,到最后整合到一个母项目中去。后台的逻辑代码根本就不用分开,用命名空间分开即可,只要在UI上面做做到分开行了,当然有些要求比较高的,就是从UI到逻辑都是分开来写的,但是我这里觉得不用,读者可以根据自己的要求来做。

  直入主题,先说一下我写的例子的主体结构,直接把解决方案的截图拿上来,看看如何分层的。

                                 

  由于本人比较热衷于DDD的学习,所以就用DDD的思想实现了这个例子,对于DDD我就不去讲解了,可以翻看具体的文章。其中主要的是03Plugins这个里面放置的就是所有的插件的UI,逻辑代码我都是放到了05Applaction中去了。

  下面我来讲一下,如何使插件用到主项目中去,也就是所谓的“站点合并”。UI层我运用的是MVC,所以合并的关键就是路由的合并,插件的路由如何进入到主项目中去。

  在06Foundation中的Framework中,我实现了这样的方法。

                          

  下面以博客插件为例子讲解一下:

其中IPlugin.cs

 //   作者:                    不要理我 CJ
  //   邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
  //   创建时间:                2012-08-8
  //   最后修改时间:            2012-08-11
  //  
 //   未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
  //   同时由于项目引起的一切问题,原作者概不负责。
  // 
 //   本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权
  // 
 //   您一旦下载就视为您已经阅读此声明。
  // 
 //   您不可以移除项目中所有的声明。 

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.Web.Routing;

  namespace   CJCMS.Framework.Plugin
{
      public   interface   IPlugin
    {
          ///   <summary> 
         ///   插件名
          ///   </summary> 
         string  PluginName {  get ;  set  ; }
        
          ///   <summary> 
         ///   插件描述
          ///   </summary> 
         string  Describtion {  get ;  set  ; }
        
          ///   <summary> 
         ///   插件路由
          ///   </summary> 
        List<Route> routes {  get ;  set  ; }
    }
} 

插件管理类:

 //   作者:                    不要理我 CJ
  //   邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
  //   创建时间:                2012-08-8
  //   最后修改时间:            2012-08-11
  //  
 //   未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议在商用,不能确保稳定性。
  //   同时由于项目引起的一切问题,原作者概不负责。
  // 
 //   本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权
  // 
 //   您一旦下载就视为您已经阅读此声明。
  // 
 //   您不可以移除项目中所有的声明。 

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   CJCMS.Framework.Routes;

  namespace   CJCMS.Framework.Plugin
{
      public   class   PluginsManger:IPluginsManger
    {
          ///   <summary> 
         ///   安装插件
          ///   </summary> 
         ///   <param name="plugin"></param> 
         ///   <returns></returns> 
         public   bool   InstallPlugin(IPlugin plugin)
        {
              try  
            {
                  ///  注册路由 
                RoutesRegister re =  new   RoutesRegister();
                re.RegisterRoute(plugin.routes);

                  ///  记录插件表
                  ///
                  return   true  ;
            }
              catch  
            {
                  return   false  ;
            }

        }

          ///   <summary> 
         ///   卸载插件
          ///   </summary> 
         ///   <param name="plugin"></param> 
         ///   <returns></returns> 
         public   bool   UnInstallPlugin(IPlugin plugin)
        {
              try  
            {
                  ///  卸载路由 
                RoutesRegister re =  new   RoutesRegister();
                re.DeleteRoute(plugin.routes);

                  ///  记录插件表
                  ///
                  return   true  ;
            }
              catch  
            {
                  return   false  ;
            }
        }
    }
} 

BlogPlugin

 //   作者:                    不要理我 CJ
  //   邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
  //   创建时间:                2012-08-8
  //   最后修改时间:            2012-08-11
  //  
 //   未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议在商用,不能确保稳定性。
  //   同时由于项目引起的一切问题,原作者概不负责。
  // 
 //   本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权
  // 
 //   您一旦下载就视为您已经阅读此声明。
  // 
 //   您不可以移除项目中所有的声明。 

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Web;
  using   CJCMS.Framework.Plugin;
  using   System.Web.Routing;
  using   System.Web.Mvc;

  namespace   CJCMS.Plugin.Blog
{
      public   class   BlogPlugin :IPlugin
    {
          public  List<Route> routes {  get ;  set  ; }

          ///   <summary> 
         ///   插件名
          ///   </summary> 
         public   string  PluginName {  get ;  set  ; }

          ///   <summary> 
         ///   插件描述
          ///   </summary> 
         public   string  Describtion {  get ;  set  ; }

          public   BlogPlugin()
        {
            routes  =  new  List<Route> ();
              /*  
             * 路由例子
            routes.Add(new Route(
                    "User/Login", 
                    new RouteValueDictionary(new { controller = "User", action = "Login" }), 
                    new System.Web.Mvc.MvcRouteHandler()));
               */  
            routes.Add(  new   Route(
                      "  {controller}/{action}/{id}/{k}  "  ,
                    
                      new   System.Web.Mvc.MvcRouteHandler()));
        }
    }
} 

这样在主项目中加载插件的时候就可以调用了。

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Web;
  using   System.Web.Mvc;
  using   System.Web.Routing;
  using   CJCMS.Framework.Plugin;
  using   CJCMS.Plugin.Blog;
  using   CJCMS.Core;

  namespace   CJCMS.Web
{
      //   注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
      //   请访问   http://go.microsoft.com/?LinkId=9394801 

     public   class   MvcApplication : System.Web.HttpApplication
    {
        

          public   static   void   RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute(  "  {resource}.axd/{*pathInfo}  "  );

            routes.MapRoute(
                  "  Default  " ,  //   路由名称 
                 "  {controller}/{action}/{id}  " ,  //   带有参数的 URL 
                 new  { controller =  "  Home  " , action =  "  Index  " , id = UrlParameter.Optional }  //   参数默认值 
             );
              /*  
             * 
             * 注册插件例子,这里应该注册安装时已经选中的插件,当然在项目已经运行的时候开启插件,也是这样子注册
             * 
            IPluginsManger ipm = new PluginsManger();
            IPlugin blogplugin = new BlogPlugin();
            ipm.InstallPlugin(blogplugin);
               */  
            IPluginsManger ipm  =  new   PluginsManger();
            IPlugin blogplugin  =  new   BlogPlugin();
            ipm.InstallPlugin(blogplugin);

              //  AutofacRepositity auto = new AutofacRepositity(builder);
              //  auto.RegisterRepositity(); 
         }

          protected   void   Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);
        }
    }
} 

最后要记得把插件UI复制到主项目中去,添加编译后指令

xcopy /s /y  "  $(ProjectDir)bin\*  "   "  $(SolutionDir)CJCMS.Web\bin\" 
xcopy /s /y  "  $(ProjectDir)Content\*  "   "  $(SolutionDir)CJCMS.Web\Content  "  
xcopy  /s /y  "  $(ProjectDir)Scripts\*  "   "  $(SolutionDir)CJCMS.Web\Scripts  "  
xcopy  /s /y /i  "  $(ProjectDir)Views\*  "   "  $(SolutionDir)CJCMS.Web\Views \Blog"

 也许这段代码

 xcopy  /s /y /i  "  $(ProjectDir)Views\*  "   "  $(SolutionDir)CJCMS.Web\Views \Blog"

 你能看出些端倪,不错,下一讲就是主讲这句话,先卖个关子。

未完待续,希望大牛给予指导和好的建议。

Just waiting. Go on  coding.

上面一讲我留下一个疑问,那就是一句编译后指令,有一些MVC基础的人,应该能够看出端倪,要是你没有看懂,那就认真的听我道来吧。

  

 1  xcopy /s /y  "  $(ProjectDir)bin\*  "   "  $(SolutionDir)CJCMS.Web\bin\" 
 2  xcopy /s /y  "  $(ProjectDir)Content\*  "   "  $(SolutionDir)CJCMS.Web\Content  " 
 3  xcopy /s /y  "  $(ProjectDir)Scripts\*  "   "  $(SolutionDir)CJCMS.Web\Scripts  " 
 4  xcopy /s /y /i  "  $(ProjectDir)Views\*  "   "  $(SolutionDir)CJCMS.Web\Views\Blog  " 

  第四行中那句代码,我解释一下,怕大家对于xcopy不大理解,这句主要就是在编译之后把,项目的Views目录的文件复制到解决方案文件

CJCMS.Web\Views\Blog 下,谁是CJCMS.Web,CJCMS.Web就是主项目,也就是把插件的Views都拷贝到CJCMS.Web下的Views/Blog去了,但是大家看一下,要是这样的话,主项目的目录结构成什么样子了。

   

  主项目的Views目录有三层,而不是两个层次,这样子如何访问到Views/Blog/Blog/Home.aspx呢,插件中的Controller结构你看一下是正常的目录,那我们遇到了一个问题,就是如何使得MVC支持多层目录。

  我在Framework中写了这么一个类,继承一下MVC的ActionFilterAttribute,来拦截到请求,然后跳转到你想要跑去的多层目录去,Folder变量就是Views多层目录中你多出来的目录,多出来就是原本MVC是两层目录,而现在变成了多层目录,在浏览器中输入localhost/Blog/Home,如何能够访问到我上面例子的三层目录呢,我其实多了一层目录Blog/,那你就可以在Controller中添加属性了。

 //   作者:                    不要理我 CJ 
  //   邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
  //   创建时间:                2012-08-8
  //   最后修改时间:            2012-08-11
  //  
 //   未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试.本项目不建议商用,不能确保稳定性
  //   同时由于项目引起的一切问题,原作者概不负责。
  // 
 //   本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权
  // 
 //   您一旦下载就视为您已经阅读此声明。
  // 
 //   您不可以移除项目中所有的声明。 

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.Web.Mvc;

  namespace   CJCMS.Framework.Routes
{
      public   class   CustomRouting : ActionFilterAttribute
    {
          public   override   void   OnActionExecuting(ActionExecutingContext filterContext)
        {
              string  value =  "  /  " +filterContext.RouteData.Values[ "  action  " ].ToString() +  "  .aspx  "  ;
            filterContext.RouteData.Values[  "  action  " ] = Folder +  value;
              base  .OnActionExecuting(filterContext);
        }

          public  CustomRouting( string   folder)
        {   this .Folder =  folder; }

          public   string  Folder {  get ;  set  ; }
    }
} 

  具体插件中的Controller怎么用这个呢?

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Web;
   5   using   System.Web.Mvc;
   6   using   CJCMS.Framework.Routes;
   7   using   CJCMS.Contracts.DTO;
   8   //  using CJCMS.Plugin.Blog.BlogServiceReference; 
  9   using   CJCMS.Plugin.Blog.BlogS;
  10   using   CJCMS.Contracts.DTO.Blog;
  11   using   System.Threading;
  12  
 13  
 14   namespace   CJCMS.Plugin.Blog.Controllers
  15   {
  16       [HandleError]
  17      [CustomRouting( "  ~/Views/Blog/Blog  "  )]
  18       public   class   BlogController : Controller
  19       {
  20         
 21           public   ActionResult Home()
  22           {
  23              ViewData[ "  Message  " ] =  "  欢迎使用 ASP.NET MVC!  "  ;
  24  
 25  
 26              BlogServiceClient service =  new   BlogServiceClient();
  27  
 28               try 
 29               {
  30                  BlogDspModel b =  new   BlogDspModel();
  31                  b.Title =  Guid.NewGuid().ToString();
  32                  b.Body =  "  123  "  ;
  33                  b.Created =  DateTime.Now;
  34                  b.Id =  Guid.NewGuid().ToString();
  35                   service.Add(b);
  36               }
  37               catch   (Exception ee)
  38               {
  39                  ViewData[ "  Message  " ] +=  ee.Message;
  40               }
  41  
 42              IList<BlogDspModel> il =  service.Fetch();
  43               service.Close();
  44               return   View();
  45           }
  46  
 47         
 48  
 49           [HttpGet]
  50           public  ActionResult Home( string  id, string   k)
  51           {
  52              ViewData[ "  Message  " ] =  "  欢迎使用 ASP.NET MVC!  "  ;
  53              BlogServiceClient service =  new   BlogServiceClient();
  54               try 
 55               {
  56                  BlogDspModel b =  new   BlogDspModel();
  57                  b.Title =  Guid.NewGuid().ToString();
  58                  b.Body =  "  123  "  ;
  59                  b.Created =  DateTime.Now;
  60                  b.Id =  Guid.NewGuid().ToString();
  61                   service.Add(b);
  62               }
  63               catch   (Exception ee)
  64               {
  65                  ViewData[ "  Message  " ] +=  ee.Message;
  66               }
  67              IList<BlogDspModel> il =  service.Fetch();
  68               service.Close();
  69               return   View();
  70           }
  71  
 72           public   ActionResult About()
  73           {
  74               return   View();
  75           }
  76       }
  77  }

  第17行你已经看到了,怎么去处理,使得MVC支持多层目录,好啦这一讲也结束了。

  下面,我会开始讲讲我写得例子的整体的架构,也就是开始讲DDD了,我的项目设计了,你准备好了吗?

  这个项目,主要使用的技术:ORM(NHibernate),MVC,WCF,DTO-DO Mapping,DDD设计理念,单例模式等等。

  希望你能够期待,要是大家感兴趣,我会选择开源,给大家看看,共同学习。

  Just waiting. Go on  coding.

 

 

标签:  DDD ,  插件 ,  架构设计

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于说说项目中的插件思想的详细内容...

  阅读:38次