小編給大家分享一下ASP.NET中MVC引擎開發(fā)插系統(tǒng)的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、石屏網(wǎng)站維護(hù)、網(wǎng)站推廣。
一、前言
我心中的插件系統(tǒng)應(yīng)該是像Nop那樣(更牛逼的如Orchard,OSGI.NET),每個(gè)插件模塊不只是一堆實(shí)現(xiàn)了某個(gè)業(yè)務(wù)接口的dll,然后采用反射或IOC技術(shù)來調(diào)用,而是一個(gè)完整的mvc小應(yīng)用,我可以在后臺(tái)控制插件的安裝和禁用,目錄結(jié)構(gòu)如下:
生成后放在站點(diǎn)根目錄下的Plugins文件夾中,每個(gè)插件有一個(gè)子文件夾
Plugins/Sms.AliYun/
Plugins/Sms.ManDao/
我是一個(gè)有強(qiáng)迫癥的的懶人,我不想將生成的dll文件拷貝到bin目錄。
二、要解決的問題
1.asp.net引擎默認(rèn)只會(huì)加載“bin”文件夾中的dll,而我們想要的插件文件則是分散在Plugins目錄下的各個(gè)子目錄中。
2.視圖中使用了模型時(shí)如何處理?默認(rèn)情況下RazorViewEngine使用BuildManager將視圖編譯成動(dòng)態(tài)程序集,然后使用Activator.CreateInstance實(shí)例化新編譯的對(duì)象,而使用插件dll時(shí),當(dāng)前的AppDomain不知道如何解析這種引用了模型的視圖,因?yàn)樗淮嬖谟凇癰in”或GAC中。更糟糕的是,不會(huì)收到任何錯(cuò)誤消息,告訴您為什么它不工作,或者問題在哪。相反,他會(huì)告訴你,從View目錄中找不到文件。
3.某個(gè)插件正掛在站點(diǎn)下運(yùn)行著,直接覆蓋插件的dll,會(huì)告訴你當(dāng)前dll正在使用,不能被覆蓋。
4.視圖文件不放站點(diǎn)的View目錄中,該如何加載。
三.Net 4.0讓這一切變成可能
Net4.0有一個(gè)新特性是在應(yīng)用程序初始化之前執(zhí)行代碼的能力(PreApplicationStartMethodAttribute),這個(gè)特性使得應(yīng)用程序在Application_Star前可以做一些工作,例如我們可以在應(yīng)用啟動(dòng)之前告知我們的mvc插件系統(tǒng)的dll放在哪,做預(yù)加載處理等。關(guān)于.net的幾個(gè)新特性,有歪果仁寫得有博客來介紹,點(diǎn)我。,關(guān)于PreApplicationStartMethodAttribute,有博友已經(jīng)寫過了,點(diǎn)我。 Abp的啟動(dòng)模塊應(yīng)該也是使用PreApplicationStartMethodAttribute這個(gè)特性原理來實(shí)現(xiàn)的,具體是不是這樣還沒看。
四、解決方案
1.修改主站點(diǎn)web.config目錄,讓運(yùn)行時(shí)除了加載bin目錄中的文件,還可以從其它目錄加載
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="Plugins/temp/" /> </assemblyBinding> </runtime>
2.開發(fā)一個(gè)簡(jiǎn)易的插件管理類,這個(gè)類的作用就是在Application_Start之前就把Plugins各子目錄中的dll拷貝到第1步指定的文件夾中,為了讓demo盡可能簡(jiǎn)單,沒有對(duì)重復(fù)的dll進(jìn)行檢測(cè)(比如插件中引用了ef程序集,主站點(diǎn)也引用了,在站點(diǎn)bin目錄中已經(jīng)存在ef的dll了,就沒必要再把插件中的dll拷貝到上面設(shè)置的動(dòng)態(tài)程序集目錄中)
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Compilation; using System.Web.Hosting; [assembly: PreApplicationStartMethod(typeof(Plugins.Core.PreApplicationInit), "Initialize")] namespace Plugins.Core { public class PreApplicationInit { static PreApplicationInit() { PluginFolder = new DirectoryInfo(HostingEnvironment.MapPath("~/plugins")); ShadowCopyFolder = new DirectoryInfo(HostingEnvironment.MapPath("~/plugins/temp")); } /// <summary> /// 插件所在目錄信息 /// </summary> private static readonly DirectoryInfo PluginFolder; /// <summary> /// 程序應(yīng)行時(shí)指定的dll目錄 /// </summary> private static readonly DirectoryInfo ShadowCopyFolder; public static void Initialize() { Directory.CreateDirectory(ShadowCopyFolder.FullName); //清空插件dll運(yùn)行目錄中的文件 foreach (var f in ShadowCopyFolder.GetFiles("*.dll", SearchOption.AllDirectories)) { f.Delete(); } foreach (var plug in PluginFolder.GetFiles("*.dll", SearchOption.AllDirectories).Where(i=>i.Directory.Parent.Name== "plugins")) { File.Copy(plug.FullName, Path.Combine(ShadowCopyFolder.FullName, plug.Name), true); } foreach (var a in ShadowCopyFolder .GetFiles("*.dll", SearchOption.AllDirectories) .Select(x => AssemblyName.GetAssemblyName(x.FullName)) .Select(x => Assembly.Load(x.FullName))) { BuildManager.AddReferencedAssembly(a); } } } }
3.如何讓View引擎找到我們的視圖呢?答案是重寫RazorViewEngine的方法,我采用了約定大于配置的方式(假設(shè)我們的插件項(xiàng)目命名空間為Plugins.Apps.Sms,那么默認(rèn)的控制器命名空間為Plugins.Apps.Sms.Controllers,插件生成后的文件夾必須為/Plugins/Plugins.Apps.Sms/),通過分析當(dāng)前控制器就可以知道當(dāng)前插件的View目錄位置
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using System.Web.WebPages.Razor; namespace Plugins.Web { public class CustomerViewEngine : RazorViewEngine { /// <summary> /// 定義視圖頁所在地址。 /// </summary> private string[] _viewLocationFormats = new[] { "~/Views/Parts/{0}.cshtml", "~/Plugins/{pluginFolder}/Views/{1}/{0}.cshtml", "~/Plugins/{pluginFolder}/Views/Shared/{0}.cshtml", "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml", }; public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { string ns = controllerContext.Controller.GetType().Namespace; string controller = controllerContext.Controller.GetType().Name.Replace("Controller", ""); //說明是插件中的控制器,View目錄需要單獨(dú)處理 if (ns.ToLower().Contains("plugins")) { var pluginsFolder = ns.ToLower().Replace(".controllers", ""); ViewLocationFormats = ReplacePlaceholder(pluginsFolder); } return base.FindView(controllerContext, viewName, masterName, useCache); } /// <summary> /// 替換pluginFolder占位符 /// </summary> /// <param name="folderName"></param> private string[] ReplacePlaceholder(string folderName) { string[] tempArray = new string[_viewLocationFormats.Length]; if (_viewLocationFormats != null) { for (int i = 0; i < _viewLocationFormats.Length; i++) { tempArray[i] = _viewLocationFormats[i].Replace("{pluginFolder}", folderName); } } return tempArray; } } }
然后在主站點(diǎn)的Global.asax中將Razor引擎指定為我們重寫過的
4.開始制作一個(gè)插件目錄,跟我們平時(shí)建立的MVC項(xiàng)目并沒有太大區(qū)別,只是發(fā)布時(shí)需要做一些設(shè)置。
.生成路徑要按照第3條的約定來寫,不然會(huì)找不到視圖文件
.View目錄下的web.config和.cshtml文件要復(fù)制到生成目錄(在文件中點(diǎn)右鍵)
3.設(shè)置引用項(xiàng)目中的生成屬性,主程序下面已經(jīng)有了的就把“復(fù)制到輸出目錄”設(shè)置為無,要不然拷貝到動(dòng)態(tài)bin目錄時(shí)會(huì)出錯(cuò),可以對(duì)第2步中的那個(gè)類改造一下,加入文件比較功能,bin目錄中沒有的,才拷貝到動(dòng)態(tài)bin目錄中。
4.生成后的目錄結(jié)構(gòu)如下:
5.跑一下,一切正常,插件中的控制器工作正常,視圖中引用了Model也沒問題
以上是“ASP.NET中MVC引擎開發(fā)插系統(tǒng)的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
網(wǎng)站題目:ASP.NET中MVC引擎開發(fā)插系統(tǒng)的示例分析
當(dāng)前URL:http://chinadenli.net/article36/ppsdpg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、軟件開發(fā)、微信公眾號(hào)、網(wǎng)站導(dǎo)航、網(wǎng)站內(nèi)鏈、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)