<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng)

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:35:44
        文檔

        使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng)

        使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng):一、前言 我心中的插件系統(tǒng)應(yīng)該是像Nop那樣(更牛逼的如Orchard,OSGI.NET),每個(gè)插件模塊不只是一堆實(shí)現(xiàn)了某個(gè)業(yè)務(wù)接口的dll,然后采用反射或IOC技術(shù)來(lái)調(diào)用,而是一個(gè)完整的mvc小應(yīng)用,我可以在后臺(tái)控制插件的安裝和禁用,目錄結(jié)構(gòu)如下: 生成后放在站點(diǎn)
        推薦度:
        導(dǎo)讀使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng):一、前言 我心中的插件系統(tǒng)應(yīng)該是像Nop那樣(更牛逼的如Orchard,OSGI.NET),每個(gè)插件模塊不只是一堆實(shí)現(xiàn)了某個(gè)業(yè)務(wù)接口的dll,然后采用反射或IOC技術(shù)來(lái)調(diào)用,而是一個(gè)完整的mvc小應(yīng)用,我可以在后臺(tái)控制插件的安裝和禁用,目錄結(jié)構(gòu)如下: 生成后放在站點(diǎn)

        一、前言

        我心中的插件系統(tǒng)應(yīng)該是像Nop那樣(更牛逼的如Orchard,OSGI.NET),每個(gè)插件模塊不只是一堆實(shí)現(xiàn)了某個(gè)業(yè)務(wù)接口的dll,然后采用反射或IOC技術(shù)來(lái)調(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目錄。

        二、要解決的問(wèn)題

        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ò)誤消息,告訴您為什么它不工作,或者問(wèn)題在哪。相反,他會(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è)新特性,有歪果仁寫得有博客來(lái)介紹,點(diǎn)我。,關(guān)于PreApplicationStartMethodAttribute,有博友已經(jīng)寫過(guò)了,點(diǎn)我。 Abp的啟動(dòng)模塊應(yīng)該也是使用PreApplicationStartMethodAttribute這個(gè)特性原理來(lái)實(shí)現(xiàn)的,具體是不是這樣還沒(méi)看。

        四、解決方案

        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.開(kāi)發(fā)一個(gè)簡(jiǎn)易的插件管理類,這個(gè)類的作用就是在Application_Start之前就把Plugins各子目錄中的dll拷貝到第1步指定的文件夾中,為了讓demo盡可能簡(jiǎn)單,沒(méi)有對(duì)重復(fù)的dll進(jìn)行檢測(cè)(比如插件中引用了ef程序集,主站點(diǎn)也引用了,在站點(diǎn)bin目錄中已經(jīng)存在ef的dll了,就沒(méi)必要再把插件中的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/),通過(guò)分析當(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>
         /// 定義視圖頁(yè)所在地址。
         /// </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", "");
         //說(shuō)明是插件中的控制器,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引擎指定為我們重寫過(guò)的

        4.開(kāi)始制作一個(gè)插件目錄,跟我們平時(shí)建立的MVC項(xiàng)目并沒(méi)有太大區(qū)別,只是發(fā)布時(shí)需要做一些設(shè)置。

        .生成路徑要按照第3條的約定來(lái)寫,不然會(huì)找不到視圖文件

        .View目錄下的web.config和.cshtml文件要復(fù)制到生成目錄(在文件中點(diǎn)右鍵)

        3.設(shè)置引用項(xiàng)目中的生成屬性,主程序下面已經(jīng)有了的就把“復(fù)制到輸出目錄”設(shè)置為無(wú),要不然拷貝到動(dòng)態(tài)bin目錄時(shí)會(huì)出錯(cuò),可以對(duì)第2步中的那個(gè)類改造一下,加入文件比較功能,bin目錄中沒(méi)有的,才拷貝到動(dòng)態(tài)bin目錄中。

        4.生成后的目錄結(jié)構(gòu)如下:

        5.跑一下,一切正常,插件中的控制器工作正常,視圖中引用了Model也沒(méi)問(wèn)題

        到此,一個(gè)插件系統(tǒng)的核心部分就算完成了,你可繼續(xù)進(jìn)行擴(kuò)展,增加插件的發(fā)現(xiàn)、安裝、卸載功能,這些相對(duì)于核心功能來(lái)說(shuō),都是小兒科。后續(xù)我會(huì)基于Abp框架出一個(gè)插件系統(tǒng)的文章,有興趣的把小板凳準(zhǔn)備好,瓜子花生買上:)

        五、源代碼

        下載Plugins鏈接: https://pan.baidu.com/s/1nvmbL81 密碼: 85v1

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng)

        使用ASP.NET MVC引擎開(kāi)發(fā)插件系統(tǒng):一、前言 我心中的插件系統(tǒng)應(yīng)該是像Nop那樣(更牛逼的如Orchard,OSGI.NET),每個(gè)插件模塊不只是一堆實(shí)現(xiàn)了某個(gè)業(yè)務(wù)接口的dll,然后采用反射或IOC技術(shù)來(lái)調(diào)用,而是一個(gè)完整的mvc小應(yīng)用,我可以在后臺(tái)控制插件的安裝和禁用,目錄結(jié)構(gòu)如下: 生成后放在站點(diǎn)
        推薦度:
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 波多野结衣一区二区免费视频| 91精品免费久久久久久久久| 青青草国产免费久久久91| 亚洲视频一区在线观看| 91精品导航在线网址免费| 中文字幕亚洲第一在线| 青青青国产在线观看免费网站| 亚洲日本精品一区二区| 国产精品成人免费福利| 亚洲三级视频在线观看| 香蕉视频在线观看免费国产婷婷 | 香蕉蕉亚亚洲aav综合| 国产午夜不卡AV免费| 亚洲视频一区调教| 免费福利网站在线观看| 亚洲国产精品无码第一区二区三区| 日本牲交大片免费观看| 永久免费观看黄网站| 久久国产亚洲电影天堂| 国产又黄又爽又猛免费app| 亚洲AV无码AV吞精久久| 久久亚洲av无码精品浪潮| 男人j进入女人j内部免费网站| 亚洲白色白色永久观看| 免费高清在线爱做视频| 国产裸体美女永久免费无遮挡| 久久精品国产亚洲AV麻豆~| 美女视频黄的全免费视频| 色费女人18女人毛片免费视频| 亚洲成色在线综合网站| 成年人免费的视频| 又黄又大的激情视频在线观看免费视频社区在线 | a级成人毛片免费视频高清| 亚洲一区无码中文字幕乱码| 日韩视频免费一区二区三区| 中文字幕成人免费高清在线视频| 亚洲黄色在线观看| 全亚洲最新黄色特级网站| 久久午夜无码免费| 黄床大片30分钟免费看| 久久精品国产亚洲av麻豆色欲|