In diesem Artikel werden hauptsächlich relevante Informationen zur Verwendung der ASP.NET MVC-Engine zur Entwicklung von Plug-In-Systemen vorgestellt. Interessierte Freunde können darauf verweisen
1. Vorwort
Das Plug-in-System sollte meiner Meinung nach wie Nop sein (bessere wie Orchard, OSGI.NET). Jedes Plug-in-Modul besteht nicht nur aus einer Reihe von DLLs, die ein bestimmtes implementieren Geschäftsschnittstelle, und verwenden Sie dann Reflection oder IOC-Technologie, aber es ist eine vollständige MVC-Kleinanwendung. Ich kann die Installation und Deaktivierung von Plug-Ins wie folgt steuern:
generiert und dann im Plugins-Ordner im Stammverzeichnis der Site abgelegt. Jedes Plug-in hat einen Unterordner
Plugins/Sms.AliYun /
Plugins/ Sms.ManDao/
Ich bin ein fauler Mensch mit Zwangsstörung und möchte die generierte DLL nicht kopieren Datei in das bin-Verzeichnis.
2. Zu lösende Probleme
1. Die asp.net-Engine lädt standardmäßig nur die DLL im Ordner „bin“. Datei, die wir wollen Es ist in verschiedenen Unterverzeichnissen im Plugins-Verzeichnis verstreut.
2. Wie gehe ich vor, wenn das Modell in der Ansicht verwendet wird? Standardmäßig verwendet RazorViewEngine BuildManager, um die Ansicht in eine dynamische Assembly zu kompilieren, und verwendet dann Activator.CreateInstance, um das neu kompilierte Objekt zu instanziieren. Bei Verwendung der Plugin-DLL weiß die aktuelle AppDomain nicht, wie eine solche Ansicht, die auf das Modell verweist, aufgelöst werden soll Existiert nicht in „bin“ oder GAC. Schlimmer noch: Sie erhalten keine Fehlermeldungen, die Ihnen erklären, warum es nicht funktioniert oder wo das Problem liegt. Stattdessen wird Ihnen mitgeteilt, dass die Datei nicht im View-Verzeichnis gefunden werden kann.
3. Durch direktes Überschreiben der Plug-in-DLL erfahren Sie, dass die aktuelle DLL verwendet wird und nicht überschrieben werden kann.
4. So laden Sie die Ansichtsdatei, wenn sie nicht im Ansichtsverzeichnis der Site abgelegt ist.
Three.Net 4.0 macht all dies möglich
Net4.0 verfügt über eine neue Funktion, nämlich die Möglichkeit, Code auszuführen, bevor die Anwendung initialisiert wird (PreApplicationStartMethodAttribute), dies Mit dieser Funktion kann die Anwendung einige Arbeiten vor Application_Star ausführen. Beispielsweise können wir vor dem Start der Anwendung feststellen, wo sich die DLL unseres MVC-Plug-In-Systems befindet, und eine Vorladeverarbeitung usw. durchführen. Bezüglich einiger neuer Funktionen von .net gibt es einen Blog von Waiguo Keren, der sie vorstellt. Klicken Sie bitte hier. , In Bezug auf PreApplicationStartMethodAttribute haben einige Blogger bereits darüber geschrieben, bitte klicken Sie hier. Das Startmodul von Abp sollte auch mit dem Feature-Prinzip von PreApplicationStartMethodAttribute implementiert werden. Ich habe nicht gesehen, ob dies der Fall ist.
4. Lösung
1. Ändern Sie das Hauptverzeichnis web.config, sodass Sie während der Laufzeit nicht nur Dateien aus dem bin-Verzeichnis laden können andere Verzeichnisse
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="Plugins/temp/" /> </assemblyBinding> </runtime>
2. Entwickeln Sie eine einfache Plug-in-Verwaltungsklasse. Die Funktion dieser Klasse besteht darin, die DLLs in jedem Unterverzeichnis von Plugins in die angegebenen zu kopieren Um die Demo so einfach wie möglich zu gestalten, werden im Schritt 1 vor dem Ordner „Application_Start“ keine doppelten DLLs erkannt (z. B. wird im Plug-In auf die EF-Assembly verwiesen, und die Hauptsite verweist auch darauf, und das gibt es auch). bereits eine EF-DLL im Site-Bin-Verzeichnis, daher besteht keine Notwendigkeit. Kopieren Sie dann die DLL im Plug-In in das oben festgelegte dynamische Assembly-Verzeichnis)
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. Wie lassen wir die View-Engine unsere Ansicht finden? Die Antwort besteht darin, RazorViewEngine neu zu schreiben. Ich habe den Ansatz der Konvention gegenüber der Konfiguration übernommen (vorausgesetzt, unser Plug-in-Projekt-Namespace ist Plugins.Apps.Sms, dann ist der Standard-Controller-Namespace Plugins.Apps.Sms.Controllers. Nach dem Plug-in wird generiert. Der Ordner muss /Plugins/Plugins.Apps.Sms/ sein. Durch die Analyse des aktuellen Controllers können Sie den Speicherort des Ansichtsverzeichnisses des aktuellen Plug-Ins ermitteln
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; } } }
und dann in der Global.asax der Hauptseite wird die Razor-Engine als unser umgeschriebenes
bezeichnet 4. Beginnen Sie mit der Erstellung eines Plug-Ins Verzeichnis, das dem MVC-Projekt, das wir normalerweise erstellen, nicht allzu ähnlich ist. Der große Unterschied besteht darin, dass Sie beim Veröffentlichen einige Einstellungen vornehmen müssen.
. Der Generierungspfad muss gemäß der Vereinbarung in Artikel 3 geschrieben werden, andernfalls wird die Ansichtsdatei nicht gefunden
.web.config und Die Die .cshtml-Datei sollte in das Build-Verzeichnis kopiert werden (klicken Sie mit der rechten Maustaste auf die Datei)
3. Legen Sie die Build-Eigenschaften im fest Referenzprojekt, das Hauptprogramm Wenn das Programm bereits vorhanden ist, setzen Sie „In Ausgabeverzeichnis kopieren“ auf „Keine“, da sonst beim Kopieren in das dynamische Bin-Verzeichnis ein Fehler auftritt. Sie können die Klasse in Schritt 2 ändern und dort eine Dateivergleichsfunktion hinzufügen Ist so etwas nicht im bin-Verzeichnis vorhanden, dann kopieren Sie es in das dynamische bin-Verzeichnis.
4. Die generierte Verzeichnisstruktur ist wie folgt:
5 Plug-in funktioniert normal, es gibt kein Problem, wenn das Modell in der Ansicht referenziert wird
An diesem Punkt ist der Kernteil eines Plug-in-Systems abgeschlossen Kann weiter erweitert und Plug-in-Erkennung und -Installation sowie Deinstallationsfunktionen hinzugefügt werden, diese sind im Vergleich zu den Kernfunktionen ein Kinderspiel. Ich werde in Zukunft einen Artikel über das Plug-in-System basierend auf dem Abp-Framework veröffentlichen. Wenn Sie interessiert sind, bereiten Sie eine kleine Bank vor und kaufen Sie Melonenkerne und Erdnüsse:)
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der MVC-Engine-Entwicklung und des Plug-in-Systems in ASP.NET. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!