目前項目的架構基本趨勢都是易擴展,易擴展主要的實現方式就是插件,在項目中所有的擴展模塊都看作為是一個插件,那最為主要的就是插件與母體如何結合起來的,接下來就來討論一下,我對於插件項目的理解和實現。同時由於本人能力有限,問題會很多,請大家批評指正。
我認為插件就是就是一個單獨的項目,到最后整合到一個母項目中去。后台的邏輯代碼根本就不用分開,用命名空間分開即可,只要在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.
$('#example').dataTable({"aoColumnDefs": [{
"aTargets": [3],
"fnCreatedCell": function(nTd, sData, oData, iRow, iCol) {
if (sData == "33") {
$(nTd).css("background-color", "blue")
}
}
}]});

