从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图...
如果你使用過一些開源CMS的話,肯定會用過其中的的插件化功能,用戶可以通過啟用或者上傳插件包的方式動態添加一些功能,那么在ASP.NET Core MVC中如何實現插件化開發呢,下面我們來探究一下。
本系列只是筆者的一些嘗試,并不表示一定正確,只是為了分享一些思路,大家可以一起討論一下,后續會不斷更新。
在ASP.NET Core中進行插件話開發,就不得不說ApplicationPart。?ApplicationPart是ASP.NET Core一個重要組件,它是應用程序資源的一種抽象,通過它可以發現程序集中包含的控制器、視圖組件、TagHelper和預編譯Razor視圖等MVC功能。
默認情況下,當一個ASP.NET Core MVC應用啟動時,它只會嘗試在當前應用啟動的項目及引用的項目中加載控制器,如果想從未直接引用的程序集中加載控制器和預編譯Razor視圖,我們就需要借助ApplicationPart了。
而ASP.NET Core MVC中,有一個ApplicaitonPartManager類, 通過ApplicationPartManager我們可以來配置當前應用中使用哪一些ApplicationPart。
例:
var assembly = Assembly.LoadFile("demo.dll");var assemblyPart = new AssemblyPart(assembly);var mvcBuilders = services.AddMvc();mvcBuilders.ConfigureApplicationPartManager(apm =>{ apm.ApplicationParts.Add(assemblyPart);});下面呢,我們通過一個最簡單的實例,給大家演示一下如何借助ApplicationPart,動態加載第三方程序集中的控制器和預編譯視圖。
首先我們創建一個ASP.NET Core MVC的站點,命名為DynamicPluginsDemoSite
然后我們同時創建一個.NET Core Class Library項目,命名為DemoPlugin1, 同時對該項目引用
Microsoft.AspNetCore.App
Microsoft.AspNetCore.Razor
Microsoft.AspNetCore.Razor.Design
注意:針對以上3個程序集,需要保證DynamicPluginsDemoSite和DemoPluigin1使用的相同的版本。
這里為了保證Razor視圖的預編譯,我們需要打開DemoPlugin1項目的工程文件DemoPlugin1.csproj。將項目使用的SDK從"Microsoft.NET.Sdk"改為"Microsoft.Net.Sdk.Razor"。
<Project Sdk="Microsoft.NET.Sdk.Razor"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <OutputPath>C:\Users\Lamond Lu\source\repos\DynamicPlugins\DynamicPluginsDemoSite\bin\Debug</OutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" /> </ItemGroup></Project>注:如果不做此修改,最后項目編譯之后,不會產生預編譯的Razor視圖程序集。(這里如果有其他更優雅的修改方式,請大家留言, 我后續會先嘗試先編寫一個項目模板來避免這個重復操作)。
下面我們開始編寫我們的插件。
這里我們首先創建一個Plugin1Controller.cs.
public class Plugin1Controller : Controller { public IActionResult HelloWorld() { return View(); } }然后我們添加一個對應的視圖文件HelloWorld.cshtml。
@{}<h1>This is Demo Plugin1.</h1>最終項目文件目錄如下:
最后我們需要修改一個項目的輸出目錄,我們需要將項目編譯的dll發送到DynamicPluginsDemoSite項目的Debug目錄中。
以上我們就完成了第一個組件的所有修改,下面我們開始修改DynamicPluginsDemoSite項目。
由于DynamicPluginsDemoSite項目不能直接引用DemoPlugin1, 所以當項目啟動時,不能自主發現DemoPlugin1項目中的控制器,所以這里我們需要使用ApplicationPart將DemoPlugin1的程序集加載到當前的運行環境中。
public void ConfigureServices(IServiceCollection services){ services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); var assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "DemoPlugin1.dll"); var mvcBuilders = services.AddMvc(); var controllerAssemblyPart = new AssemblyPart(assembly); mvcBuilders.ConfigureApplicationPartManager(apm => { apm.ApplicationParts.Add(controllerAssemblyPart); }); mvcBuilders.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}代碼解釋:
由于前一步中, 我們將DemoPlugin1的程序集輸出到了DynamicPluginsDemoSite的Debug目錄中,所以這里我們可以使用Assembly.LoadFile方法將它加載。
這里我們使用AssemblyPart類,將加載程序集封裝成一個ApplicationPart.
mvcBuilders對象的ConfigureApplicationPartManager方法可以用來配置當前項目中使用的ApplicationPart
加載完控制器之后,我們還需要加載插件的預編譯Razor視圖。這里和之前的稍有不同,我們需要使用CompileRazorAssemblyPart來封裝加載的預編譯Razor視圖。
public void ConfigureServices(IServiceCollection services){ services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); var assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "DemoPlugin1.dll"); var assemblyView = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "DemoPlugin1.Views.dll"); var viewAssemblyPart = new CompiledRazorAssemblyPart(assemblyView); var controllerAssemblyPart = new AssemblyPart(assembly); var mvcBuilders = services.AddMvc(); mvcBuilders.ConfigureApplicationPartManager(apm => { apm.ApplicationParts.Add(controllerAssemblyPart); apm.ApplicationParts.Add(viewAssemblyPart); }); mvcBuilders.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}現在我們啟動DynamicPluginsDemoSite,在瀏覽器中輸入/Plugin1/HelloWorld, 我們的插件就正常啟用了。
注意:在啟動DynamicPluginsDemoSite站點之前,請務必先編譯DemoPlugin1項目,這樣DemoPlugin1產生的程序集才會輸出到DynamicPluginsDemoSite中。
以上只是實現了一個最簡單的MVC插件功能,要想完善整個項目,后續還有很多工作要做
需要創建一個插件模板,來避免一些重復操作。
需要將插件的模型和業務抽象出來。
需要改用數據庫來保存插件信息。
需要支持實現插件的管理以及插件的升級。
后續我會慢慢實現以上功能,大家敬請期待。
原文地址:https://www.cnblogs.com/lwqlun/p/11137788.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NetCore中三种注入生命周期的思考
- 下一篇: .NET分布式框架 | Orleans