标签:
现在正在做的项目是以长沙某个客户的需求为原型进行开发的,随着业务的拓展,其他城市相同行业的客户也有类似的需求,在进行投标时,每个客户都有自己的页面和功能要求,如果单纯用长沙客户的软件版本,无法完全满足标书要求,因此需要对项目进行改造,考虑采用MVC插件化方式。
现有项目使用的技术点主要是MVC+EF+jQuery,改造思路考虑将每一个功能模块抽取为一个插件,在主Web项目中引用各插件,并将插件的css、js、views等文件拷贝到主Web项目的Plugins文件夹下。当有新客户提出个性化需求时,将涉及到的模块插件复制一份,然后进行个性化改造,新插件和原插件在mvc 路由上一模一样,插件的名称也一样,这样对于主Web项目来说两个插件就如同一个一样。项目其他层(Biz、Model等其他类库)保持不变。
具体改造方法:
插件是一个MVC项目,要求必须包含:Controllers(控制器)、Models(ViewModel)、Content(样式表)、Scripts、Views文件夹。
项目属性中的生成事件中,添加后期生成事件命令行:
rd /s /q $(SolutionDir)MyApplication.Web\Plugins\Device xcopy /s /y $(ProjectDir)Views $(SolutionDir)MyApplication.Web\Plugins\Device\Viewsxcopy /s /y $(ProjectDir)Content $(SolutionDir)MyApplication.Web\Plugins\Device\Contentxcopy /s /y $(ProjectDir)Scripts $(SolutionDir)MyApplication.Web\Plugins\Device\Scripts\
分别用于:清空删除主Web项目插件目录、拷贝视图文件夹到主Web项目、拷贝样式表文件夹到主Web项目、拷贝js文件夹到主Web项目。这样就能实现在插件编译通过后,自动将相应的插件文件复制到主Web项目的Plugins下,方便调试。
每个插件中都添加一个自启动类(要求是静态的)PluginStartUp,类中包含:插件名称、初始化方法、Razor静态文件导入扩展(css、js)。
1.自启动类属性
.Net Framework 4.0后提供了PreApplicationStartMethodAttribute属性,提供对应用程序启动的扩展支持。
https://msdn.microsoft.com/zh-cn/library/system.web.preapplicationstartmethodattribute.aspx
使用时,将PreApplicationStartMetod的声明写在自启动类的命名空间前。
[assembly: System.Web.PreApplicationStartMethod(typeof(MyApplication.Plugins.Device.PluginStartUp), "Init")] namespace MyApplication.Plugins.Device { /// <summary> /// 插件自启动类,用于注册插件 /// </summary> public static class PluginStartUp { } }
2.插件名称
插件名称为自启动类的属性,作为本插件的唯一标识。
public static string Name { get { return "Device"; } }
3.插件初始化方法
初始化包括注册路由和Razor视图引擎。
将插件中的Controller注册为一个Area,主Web项目引用插件后就会把每一个插件当作一个域。
注册视图引擎,主要是添加View的寻找路径,即/Plugins/插件名称/Views 路径。
/// <summary> /// 插件初始化 /// </summary> public static void Init() { RegRoute(); RegViewEngine(); } /// <summary> /// 注册视图引擎 /// </summary> private static void RegViewEngine() { ViewEngines.Engines.Add(new RazorViewEngine { AreaViewLocationFormats = new[] { "~/Plugins/" + Name + "/Views/{1}/{0}" } }); } /// <summary> /// 注册插件路由 /// </summary> public static void RegRoute() { RouteTable.Routes.MapRoute( "Device", "/Device/{controller}/{action}/{id}", new { controller = "DeviceHome", action = "Index", id = UrlParameter.Optional }).DataTokens["area"] = Name; }
4.Razor扩展方法
在View页面中引入css和js文件时,如果用插件中的相对路径,在引入到主Web项目后则会找不到文件,因此需要提供一个导入css和js文件的Html扩展方法,在View页面中使用该方法引入文件,方法内将路径格式化。
/// <summary> /// 导入css, Razor Html扩展 /// </summary> /// <param name="helper"></param> /// <param name="cssName"></param> /// <returns></returns> public static IHtmlString ImportCss(this HtmlHelper helper, string cssName) { return helper.Raw(string.Format("<link href=\"/Plugins/{0}/Content/{1}\" type=‘text/css‘ rel=‘stylesheet‘ />", Name, cssName)); } /// <summary> /// 导入js, Razor Html扩展 /// </summary> /// <param name="helper"></param> /// <param name="jsName"></param> /// <returns></returns> public static IHtmlString ImportJs(this HtmlHelper helper, string jsName) { return helper.Raw(string.Format("<script src=\"/Plugins/{0}/Scripts/{1}\" ></script>", Name, jsName)); }
在View页面内,使用这两个扩展方法引入文件。
@Html.ImportCss("device.css") @Html.ImportJs("device.js")
以上就完成了原项目插件化的改造。主Web项目添加对插件的引用,当项目启动时,PluginStartUp类自动运行完成插件初始化。
当有新项目个性化需求时,只需将插件复制一份,并修改插件内的controller、view、content、scripts等,Biz、Model都无需变化(前提是项目的主业务流程是一致的),主Web项目也无需变动,发布时,根据项目的情况,需要哪些插件就在Plugins下面保留哪些插件即可。
标签:
原文地址:http://www.cnblogs.com/longyunshiye/p/5786446.html