最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2017年05月09日 10:39:53   作者:產(chǎn)品經(jīng)理是條狗  
這篇文章主要為大家詳細介紹了使用ASP.NET MVC引擎開發(fā)插件系統(tǒng)的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、前言

我心中的插件系統(tǒng)應該是像Nop那樣(更牛的如Orchard,OSGI.NET),每個插件模塊不只是一堆實現(xiàn)了某個業(yè)務接口的dll,然后采用反射或IOC技術(shù)來調(diào)用,而是一個完整的mvc小應用,我可以在后臺控制插件的安裝和禁用,目錄結(jié)構(gòu)如下:

生成后放在站點根目錄下的Plugins文件夾中,每個插件有一個子文件夾

Plugins/Sms.AliYun/

Plugins/Sms.ManDao/

我是一個有強迫癥的的懶人,我不想將生成的dll文件拷貝到bin目錄。

二、要解決的問題

1.asp.net引擎默認只會加載“bin”文件夾中的dll,而我們想要的插件文件則是分散在Plugins目錄下的各個子目錄中。

2.視圖中使用了模型時如何處理?默認情況下RazorViewEngine使用BuildManager將視圖編譯成動態(tài)程序集,然后使用Activator.CreateInstance實例化新編譯的對象,而使用插件dll時,當前的AppDomain不知道如何解析這種引用了模型的視圖,因為它不存在于“bin”或GAC中。更糟糕的是,不會收到任何錯誤消息,告訴您為什么它不工作,或者問題在哪。相反,他會告訴你,從View目錄中找不到文件。

3.某個插件正掛在站點下運行著,直接覆蓋插件的dll,會告訴你當前dll正在使用,不能被覆蓋。

4.視圖文件不放站點的View目錄中,該如何加載。

三.Net 4.0讓這一切變成可能

Net4.0有一個新特性是在應用程序初始化之前執(zhí)行代碼的能力(PreApplicationStartMethodAttribute),這個特性使得應用程序在Application_Star前可以做一些工作,例如我們可以在應用啟動之前告知我們的mvc插件系統(tǒng)的dll放在哪,做預加載處理等。關(guān)于.net的幾個新特性,有歪果仁寫得有博客來介紹,點我。,關(guān)于PreApplicationStartMethodAttribute,有博友已經(jīng)寫過了,點我。 Abp的啟動模塊應該也是使用PreApplicationStartMethodAttribute這個特性原理來實現(xiàn)的,具體是不是這樣還沒看。

四、解決方案

1.修改主站點web.config目錄,讓運行時除了加載bin目錄中的文件,還可以從其它目錄加載

 <runtime>
 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <probing privatePath="Plugins/temp/" />
 </assemblyBinding>
 </runtime>

2.開發(fā)一個簡易的插件管理類,這個類的作用就是在Application_Start之前就把Plugins各子目錄中的dll拷貝到第1步指定的文件夾中,為了讓demo盡可能簡單,沒有對重復的dll進行檢測(比如插件中引用了ef程序集,主站點也引用了,在站點bin目錄中已經(jīng)存在ef的dll了,就沒必要再把插件中的dll拷貝到上面設置的動態(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>
  /// 程序應行時指定的dll目錄
  /// </summary>
  private static readonly DirectoryInfo ShadowCopyFolder;

  public static void Initialize()
  {
   Directory.CreateDirectory(ShadowCopyFolder.FullName);
   //清空插件dll運行目錄中的文件
   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的方法,我采用了約定大于配置的方式(假設我們的插件項目命名空間為Plugins.Apps.Sms,那么默認的控制器命名空間為Plugins.Apps.Sms.Controllers,插件生成后的文件夾必須為/Plugins/Plugins.Apps.Sms/),通過分析當前控制器就可以知道當前插件的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目錄需要單獨處理
   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;
  }
 }
}


然后在主站點的Global.asax中將Razor引擎指定為我們重寫過的

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

.生成路徑要按照第3條的約定來寫,不然會找不到視圖文件

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

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

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

5.跑一下,一切正常,插件中的控制器工作正常,視圖中引用了Model也沒問題

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

五、源代碼

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

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 理解ASP.NET Core 依賴注入(Dependency Injection)

    理解ASP.NET Core 依賴注入(Dependency Injection)

    把有依賴關(guān)系的類放到容器中,解析出這些類的實例,就是依賴注入。目的是實現(xiàn)類的解耦。本文主要介紹了ASP.NET Core 依賴注入(Dependency Injection),需要了解具體內(nèi)容的可以仔細閱讀這篇文章,希望對你有所幫助
    2021-09-09
  • ASP.NET中ListView(列表視圖)的使用前臺綁定附源碼

    ASP.NET中ListView(列表視圖)的使用前臺綁定附源碼

    ListView(列表視圖)想必大家都知道吧,接下來本文將介紹下ListView的使用前臺綁定,感興趣的你可不要錯過本文了哈
    2013-03-03
  • 關(guān)于EF的Code?First的使用以及踩坑記錄

    關(guān)于EF的Code?First的使用以及踩坑記錄

    這篇文章主要介紹了關(guān)于EF的Code?First的使用以及踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • ASP.NET?Core中Razor頁面與MVC區(qū)別介紹

    ASP.NET?Core中Razor頁面與MVC區(qū)別介紹

    這篇文章介紹了ASP.NET?Core中Razor頁面與MVC的區(qū)別,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • WPF框架Prism中區(qū)域Region用法介紹

    WPF框架Prism中區(qū)域Region用法介紹

    這篇文章介紹了WPF框架Prism中區(qū)域Region用法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-02-02
  • ASP.NET MVC中使用Bundle打包壓縮js和css的方法

    ASP.NET MVC中使用Bundle打包壓縮js和css的方法

    這篇文章主要為大家詳細介紹了ASP.NET MVC中使用Bundle打包壓縮js和css的方法,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 給Repeater控件里添加序號的5種才常見方法介紹

    給Repeater控件里添加序號的5種才常見方法介紹

    Repeater是我們經(jīng)常用的一個顯示數(shù)據(jù)集的數(shù)據(jù)控件那么我們該怎么為Repeater控件添加序號呢?下面編輯為大家介紹幾種常用的為Repeater控件添加序號的方法
    2013-09-09
  • 開源跨平臺運行服務插件TaskCore.MainForm

    開源跨平臺運行服務插件TaskCore.MainForm

    這篇文章主要為大家詳細介紹了開源跨平臺運行服務插件TaskCore.MainForm的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Entity?Framework導航屬性介紹

    Entity?Framework導航屬性介紹

    這篇文章介紹了Entity?Framework的導航屬性,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • C#/VB.NET 在Word中添加條碼、二維碼的示例代碼

    C#/VB.NET 在Word中添加條碼、二維碼的示例代碼

    這篇文章主要介紹了C#/VB.NET 如何在Word中添加條碼、二維碼,代碼中將分為在Word正文段落中、頁眉頁腳中等情況來添加。感興趣的朋友可以了解下
    2020-07-07

最新評論

文安县| 沈丘县| 临湘市| 巴林左旗| 那曲县| 江阴市| 北碚区| 安岳县| 于田县| 秀山| 佛学| 曲周县| 临沧市| 堆龙德庆县| 高唐县| 右玉县| 出国| 海南省| 新巴尔虎右旗| 沭阳县| 霍州市| 佛坪县| 文山县| 肇东市| 遵义县| 尉氏县| 闵行区| 犍为县| 平阴县| 九江市| 嘉义县| 南澳县| 彰化市| 蒙山县| 搜索| 肥西县| 马龙县| 吉安县| 灌阳县| 镇坪县| 伊吾县|