使用NetCore3.1完成框架基本開發后實際應用于專案,需要保證框架的獨立性與專案的個性化, 就需要類似于下圖的插件化形式將專案放入框架這個容器中啟動,下面開始詳細介紹實作步驟

?
專案dll掃描
在框架根目錄創建Plugin檔案夾,專案在生成后事件使用copy命令拷貝至Plugin檔案夾,框架啟動時會掃描該檔案夾并進行ShadowCopy到PluginTemplate檔案夾中
private static void ScanPlugin() { if (!PluginFolder.Exists) { PluginFolder.Create(); } if (!TempPluginFolder.Exists) { TempPluginFolder.Create(); } TempPluginFolder.Attributes = FileAttributes.Normal & FileAttributes.Directory; PluginFolder.Attributes = FileAttributes.Normal & FileAttributes.Directory; //清理臨時檔案, foreach (var file in TempPluginFolder.GetFiles("*.dll", SearchOption.AllDirectories)) { try { File.SetAttributes(file.FullName, FileAttributes.Normal); file.Delete(); } catch (Exception e) { throw new Exception("請檢查IIS權限"); } } //復制插件進臨時檔案夾, foreach (var plugin in PluginFolder.GetFiles("*.dll", SearchOption.AllDirectories)) { try { string CopyFilePath = Path.Combine(TempPluginFolder.FullName, plugin.Name); File.Copy(plugin.FullName, CopyFilePath, true); File.SetAttributes(CopyFilePath, FileAttributes.Normal); } catch (Exception e) { throw new Exception("請檢查IIS權限"); } } }
專案dll加載
直接使用ApplicationParts加載AssemblyPart即可
public static void LoadPlugin() { ScanPlugin(); IEnumerable<Assembly> AssemblyList = GetPluginAssemblies(); foreach (Assembly assembly in AssemblyList) { foreach (var type in assembly.GetTypes()) { if (type.IsAssignableFrom(typeof(Controller)) && type.Name.Contains("Controller") && type.IsClass && !type.IsAbstract) { string Name = type.Name; //如果有自定義的路由注解 if (type.IsDefined(typeof(Route), false)) { var areaattribute = type.GetCustomAttributes(typeof(Route), false).FirstOrDefault(); Name = ((Route)areaattribute).Name; Name += "Controller"; } if (!ControllerTypeDic.ContainsKey(Name)) { ControllerTypeDic.Add(Name, type); } } } var controllerAssemblyPart = new AssemblyPart(assembly); CloudUtil.GetBuilder().ConfigureApplicationPartManager(apm => { apm.ApplicationParts.Add(controllerAssemblyPart); }); } CloudUtil.GetBuilder().SetCompatibilityVersion(CompatibilityVersion.Version_3_0); StartPluginRefreshWatch(); }
專案視圖
專案的cshtml視圖檔案可以手動拷貝到部署的框架Views檔案夾中(正式環境),也可以通過監控當前專案的Views檔案夾,如果變動進行自動拷貝(開發環境)
private static void StartPluginRefreshWatch() { _FileSystemWatcher.Path = CloudUtil.GetContentPath() + "/Plugin"; _FileSystemWatcher.Filter = "*.dll"; _FileSystemWatcher.Changed += _FileSystemWatcher_Changed; _FileSystemWatcher.IncludeSubdirectories = true; _FileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size; _FileSystemWatcher.EnableRaisingEvents = true; if (AppConfigUtil.Configuration["Frame:ViewsPublishType"]=="AutoCopy" && !string.IsNullOrEmpty(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]) && Directory.Exists(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"])) { FileSystemWatcher ViewsWatcher = new FileSystemWatcher(); ViewsWatcher.Path = AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]; ViewsWatcher.Changed += ViewsWatcher_Changed; ViewsWatcher.IncludeSubdirectories = true; ViewsWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size; ViewsWatcher.EnableRaisingEvents = true; //系統啟動時整個檔案夾拷貝 DirectoryInfo FrameWorkViews = new DirectoryInfo(CloudUtil.GetContentPath() + "/Views"); DirectoryInfo ProjectViews = new DirectoryInfo(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]); foreach (DirectoryInfo FDir in FrameWorkViews.GetDirectories()) { foreach (DirectoryInfo PDir in ProjectViews.GetDirectories()) { if (PDir.Name== FDir.Name) { FileUtil.DeleteDirectoryContent(FDir.FullName); } } } FileUtil.CopyDirectory(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"],CloudUtil.GetContentPath() + "/Views", true); } }
專案dll熱更新
監控Plugin檔案夾,若有變呼叫IApplicationLifetime的StopApplication重啟系統
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IConfiguration configuration, Microsoft.AspNetCore.Hosting.IApplicationLifetime applicationLifetime) { CloudUtil.SetAPP(applicationLifetime); } private static void _FileSystemWatcher_Changed(object sender, FileSystemEventArgs e) { CloudUtil.Restrat(); } public static void Restrat() { APP.StopApplication(); }
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/267257.html
標籤:.NET Core
上一篇:Mock 框架 Moq 的使用
