国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - 使用ASP.NET MVC引擎開發(fā)插件系統(tǒng)

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

2020-05-04 15:55產(chǎn)品經(jīng)理是條狗 ASP.NET教程

這篇文章主要為大家詳細(xì)介紹了使用ASP.NET MVC引擎開發(fā)插件系統(tǒng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、前言

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

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

生成后放在站點(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í)例化新編譯的對象,而使用插件dll時(shí),當(dāng)前的AppDomain不知道如何解析這種引用了模型的視圖,因?yàn)樗淮嬖谟?ldquo;bin”或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目錄中的文件,還可以從其它目錄加載

?
1
2
3
4
5
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 <probing privatePath="Plugins/temp/" />
</assemblyBinding>
</runtime>

2.開發(fā)一個(gè)簡易的插件管理類,這個(gè)類的作用就是在Application_Start之前就把Plugins各子目錄中的dll拷貝到第1步指定的文件夾中,為了讓demo盡可能簡單,沒有對重復(fù)的dll進(jìn)行檢測(比如插件中引用了ef程序集,主站點(diǎn)也引用了,在站點(diǎn)bin目錄中已經(jīng)存在ef的dll了,就沒必要再把插件中的dll拷貝到上面設(shè)置的動(dòng)態(tài)程序集目錄中)

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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目錄位置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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引擎指定為我們重寫過的

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

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

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

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

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

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

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

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

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

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

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

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

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

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

五、源代碼

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久亚洲欧美日韩精品专区 | 一区二区视频免费 | 97伦理片| 欧美大片aaaa在线观看 | 亚洲色视频 | 日韩国产一区二区 | 国产99精品| 久久久www成人免费无遮挡大片 | 草草在线观看 | 国产亲子乱弄免费视频 | 精品国产欧美一区二区 | 免费成人在线观看视频 | 一区二区不卡视频 | 午夜精品久久久久久久久久久久久 | 中日韩黄色大片 | 亚洲免费影院 | 色女人av | 激情视频网 | 有码一区 | 亚洲第一福利视频 | 久久久一二三 | 欧美顶级毛片在线播放 | 在线a视频网站 | 人人爱人人爽 | 污污的免费网站 | 精品91久久| 亚洲免费视频网 | 欧美日韩国产一区二区 | 亚洲视频播放 | 精品无码久久久久久久动漫 | 亚洲精品在线视频 | 国产精品视频导航 | 99精品久久久 | 亚洲色视频 | 成年人在线观看视频 | 亚洲一区中文字幕在线观看 | 久久精品夜夜夜夜夜久久 | 久久久久999| 亚洲第十页 | www.色小妹 | 日韩精品一区二区三区丰满 |