この記事では、主に ASP.NET MVC エンジンを使用してプラグイン システムを開発するための関連情報を詳しく紹介します。興味のある方は参考にしてください。 1. はじめに
私の頭の中にあるプラグイン システムは Nop のようなものでなければなりません (Orchard や OSGI.NET のようなもっと素晴らしいもの) それぞれのプラグイン モジュールは、特定のビジネス インターフェース
を実装する単なるdll の集まりではありません。これはリフレクションまたは IOC テクノロジーによって呼び出されますが、インストールとプラグインの無効化をバックグラウンドで制御できる完全な mvc アプリケーションです。ディレクトリ構造は次のとおりです。 プラグインは生成され、サイトのルートディレクトリに配置されます。各プラグインにはサブフォルダーがあります
Plugins/Sms.AliYun/
Plugins/Sms.ManDao/強迫性障害のある怠け者なので、dll ファイルを生成したくないのですが、bin ディレクトリにコピーされます。
2. 解決すべき問題
1. asp.net エンジンはデフォルトで dll を「bin」フォルダーにのみロードしますが、必要なプラグイン ファイルは Plugins ディレクトリの下のさまざまなサブディレクトリに分散されます。 。
2. viewで使用される
modelをどう扱うか?デフォルトでは、
RazorViewEngine は BuildManager を使用してビューを動的アセンブリにコンパイルし、次に Activator.CreateInstance を使用して新しくコンパイルされた object をインスタンス化しますが、プラグイン DLL を使用する場合、現在の AppDomain はインスタンス化しません。それを解決する方法を知っています。これは、「bin」または GAC に存在しないため、モデルのビューを 参照 します。さらに悪いことに、機能しない理由や問題の内容を示すエラー メッセージが表示されません。代わりに、ファイルが View ディレクトリに見つからないことが通知されます。 3. サイトでプラグインが実行されている場合、プラグインの dll を直接上書きすると、現在の dll が使用中であるため上書きできないことが通知されます。 4. ビューファイルがサイトのビューディレクトリに配置されていない場合にロードする方法。
Three.Net 4.0 はこれをすべて可能にしますNet4.0 には、アプリケーションが初期化される前にコードを実行する機能 (PreApplicationStartMethodAttribute) があるため、アプリケーションは Application_Star の前にいくつかの作業を行うことができます。たとえば、アプリケーションの起動前に mvc プラグイン システムに dll が配置される場所を伝え、プリロード処理などを実行できます。 .net のいくつかの新機能については、Waiguo Keren が書いたブログで紹介されています。ここをクリックしてください。 , PreApplicationStartMethodAttribute については、すでに何人かのブロガーが書いていますので、ここをクリックしてください。 Abp のスタートアップ モジュールも、PreApplicationStartMethodAttribute の機能原則を使用して実装される必要があります。これが当てはまるかどうかはわかりません。
4. 解決策
1. 実行時に bin ディレクトリにファイルをロードできるように、
他のディレクトリからもロードできるように <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Plugins/temp/" />
</assemblyBinding>
</runtime>
2.プラグイン管理クラス。このクラスの機能は、Application_Start の前に、プラグインの各サブディレクトリ内の DLL を手順 1 で指定したフォルダーにコピーすることです。 ef アセンブリはメイン サイトからも参照されるため、プラグイン内の dll をメイン サイトにコピーする必要はありません。上記で設定した動的アセンブリ ディレクトリ)
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. ビューの作成方法エンジンはビューをどこで見つけますか?答えは、RazorViewEngine を書き直すことです (プラグイン プロジェクト 名前空間 が Plugins.Apps.Sms であると仮定すると、デフォルトの
controller名前空間は 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; } } }
次に、Razor エンジンを指定します。メインサイトのGlobal.asax内 私たちのために書き直されました
4. プラグイン ディレクトリの作成を開始します。これは、通常構築する MVC プロジェクトとあまり変わりません。公開するときにいくつかの設定が必要です。
。第 3 条の規約に従って生成パスを記述する必要があります。そうしないと、ビュー ファイルが見つかりません
。View ディレクトリ内の web.config ファイルと .cshtml ファイルを生成ディレクトリにコピーする必要があります。 (ファイルを右クリックします)
3. メイン プログラムの下に生成された 属性 が既に存在する場合は、「出力ディレクトリにコピー」を「なし」に設定します。動的 bin ディレクトリにコピーするときにエラーが発生する場合は、手順 2 のクラスを変更し、ファイル比較関数を追加して、bin ディレクトリにないファイルを動的 bin ディレクトリにコピーします。
4. 生成されたディレクトリ構造は次のとおりです:
5. 実行すると、すべてが正常に動作し、Model がビューで参照されます。問題ありません
この時点で、プラグイン システムのコア部分が完成しました。プラグインの検出、インストール、アンインストール機能は、コア機能に比べれば簡単に拡張および追加できます。 。今後、Abpフレームワークをベースにしたプラグインシステムについて記事を公開する予定ですので、興味があれば小さなベンチを用意してメロンの種とピーナッツを買ってください:)
以上がASP.NETでMVCエンジンを利用したプラグインシステム開発の具体例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。