Heim  >  Artikel  >  Backend-Entwicklung  >  Detailliertes Beispiel für die Entwicklung eines Plug-in-Systems mithilfe der MVC-Engine in ASP.NET

Detailliertes Beispiel für die Entwicklung eines Plug-in-Systems mithilfe der MVC-Engine in ASP.NET

黄舟
黄舟Original
2017-05-21 11:23:532146Durchsuche

In diesem Artikel werden hauptsächlich relevante Informationen zur Verwendung der ASP.NET MVC-Engine zur Entwicklung von Plug-in-Systemen ausführlich vorgestellt. Es hat einen gewissen Referenzwert . Interessierte Freunde können sich auf

1. Einführung

Das Plug-in-System in meinem Kopf sollte wie Nop (weitere tolle wie Orchard, OSGI.NET) beziehen. , jedes Plug-in-Modul ist nicht nur eine Reihe von dll, die eine bestimmte Geschäftsschnittstelle implementieren und dann mithilfe von Reflection- oder IOC-Technologie aufgerufen werden, sondern eine vollständige kleine MVC-Anwendung, I kann die Installation und Deaktivierung des Plug-ins im Hintergrund steuern. Die Verzeichnisstruktur ist wie folgt:

generiert und im Stammverzeichnis der Site abgelegt. Jedes Plug-in verfügt über einen Unterordner

Plugins/Sms.AliYun/

Plugins/Sms.ManDao/

Ich bin ein fauler Mensch mit Zwangsstörung und möchte die generierte DLL-Datei nicht in das bin-Verzeichnis kopieren.

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. Was ist zu tun, wenn

Modell in 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, während bei Verwendung der Plugin-DLL die aktuelle Ap pDomain weiß nicht, wie diese Ansicht analysiert werden soll, die auf ein Modell verweist, da sie nicht in „bin“ oder im GAC vorhanden ist. 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 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). 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 zusätzlich zum Laden von Dateien im Bin-Verzeichnis auch Dateien laden können from

other Verzeichnis laden

 <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 den angegebenen Ordner zu kopieren Schritt 1 vor Application_Start. Um die Demo so einfach wie möglich zu gestalten, werden keine doppelten DLLs erkannt (z. B. wird im Plug-in auf die EF-Assembly verwiesen und die Hauptseite verweist auch darauf. Es ist bereits eine EF-DLL vorhanden

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 wir die View-Engine unsere Ansicht finden lassen ? Die Antwort besteht darin, RazorViewEngine neu zu schreiben. Ich habe den Ansatz der Konvention anstelle der Konfiguration übernommen (vorausgesetzt, unser Plug-in-Projekt

Namespace ist Plugins.Apps.Sms, dann ist der Standard- Controller Namespace für Plugins). .Apps.Sms.Controllers, der Ordner nach der Generierung des Plug-Ins 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;
  }
 }
}
Geben Sie dann die Razor-Engine als unsere neu geschriebene

in der Global.asax der Hauptseite an

4. Beginnen Sie mit der Erstellung eines Plug-In-Verzeichnisses, das sich nicht wesentlich von dem MVC-Projekt unterscheidet, das wir normalerweise erstellen. Beim Veröffentlichen sind lediglich einige Einstellungen erforderlich.

. 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. Richten Sie den Build im ein referenziertes Projekt Attribut , wenn es bereits im Hauptprogramm vorhanden ist, setzen Sie „In Ausgabeverzeichnis kopieren“ auf „Keine“, andernfalls tritt beim Kopieren in das dynamische Bin-Verzeichnis ein Fehler auf. Sie können die Klasse in Schritt 2 ändern und Dateivergleich hinzufügen Funktionen, die sich nicht im bin-Verzeichnis befinden, werden in das dynamische bin-Verzeichnis kopiert.

4. Die generierte Verzeichnisstruktur ist wie folgt:

5 das Plug-in Der Controller funktioniert normal und es gibt kein Problem, wenn das Modell in der Ansicht referenziert wird

An diesem Punkt der Kernteil Die Installation eines Plug-in-Systems ist abgeschlossen und Sie können mit der Erweiterung und dem Hinzufügen von Plug-in-Erkennungs-, Installations- und Deinstallationsfunktionen fortfahren. Dies ist im Vergleich zu den Kernfunktionen ein Kinderspiel. Ich werde in Zukunft einen Artikel über das Plug-in-System auf Basis des AbpFrameworks veröffentlichen. Wenn Sie Interesse haben, bereiten Sie eine kleine Bank vor und kaufen Sie Melonenkerne und Erdnüsse:)

Das obige ist der detaillierte Inhalt vonDetailliertes Beispiel für die Entwicklung eines Plug-in-Systems mithilfe der MVC-Engine in ASP.NET. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn