OrchardCore 如何动态加载模块?

开发 前端
若对OrchardCore有所了解的童鞋应该知道,OrchardCore本身定位于CMS系统,同时整个架构并非前后分离,采用MVC模式开发,基于此,由于内置需要预编译视图以及考虑其他等等原因,不支持动态加载模块,本文给出我所想到的动态加载模块方案。

[[393778]]

本文转载自微信公众号「JeffckyShare」,作者Jeffcky 。转载本文请联系JeffckyShare公众号。  

若对OrchardCore有所了解的童鞋应该知道,OrchardCore本身定位于CMS系统,同时整个架构并非前后分离,采用MVC模式开发,基于此,由于内置需要预编译视图以及考虑其他等等原因,不支持动态加载模块,本文给出我所想到的动态加载模块方案

OrchardCore基本使用示例

OrchardCore采用包管理各个模块,所以有自建NuGet,我们提前配置好OrchardCore程序包源

项目采用前后分离,所以我们创建WebAPi应用程序,为支持模块化开发,如上图下载模块开发应用程序包

紧着在Startup文件中,添加OrchardCore服务以及使用其中间件,如下图

至此一个基本的模块化项目就创建完毕,接下来我们创建模块,官方提供模块包模板引擎

通过对应命令将模板引擎下载至本地

  1. dotnet new -i OrchardCore.ProjectTemplates::1.0.0-rc2-16113 --nuget-source https://nuget.cloudsmith.io/orchardcore/preview/v3/index.json 

然后我们在项目解决方案下,继续通过CLI将下载至本地模板引擎来创建模块项目,并引入到项目解决方案中

  1. dotnet new ocmodulecms -n Test 

由于我们用不到视图,所以将视图文件夹以及对应默认安装包删除,只需保留如下模块包就好

  1. OrchardCore.Module.Targets 

同时也一并将项目文件中支持MVC配置给删除,否则会生成视图程序集,猜测应该会引起模块加载依赖需额外加载视图dll

我们将模块默认创建控制器修改为访问接口形式,方便接下来测试验证

那么接下来我们应该如何将开发好的模块进行加载呢?

OrchardCore动态加载模块(前后分离)

了解OrchardCore基本原理的我们应该知道,默认情况下,主项目添加模块引用时,会通过MSBuild在对应模块程序集中,添加模块标识,如下:

如上图所示,一个是模块标识,一个是对应文件路径标识

当启动主项目时,会找到对应程序集模块标识,并注册服务以及其他操作,如此看来,我们只需深入了解源码中是否存在存储对应模块信息的接口呢?

查看底层模块设施源码,得知对外暴露其接口即IModuleNamesProvider

好家伙,我们将生成模块dll放在主项目程序启动modules目录下,接下来我们实现该接口,如下:

  1. public class DynamicModuleNamesProvider : IModuleNamesProvider 
  2.     private readonly List<string> _moduleNames = new List<string>(); 
  3.  
  4.     public DynamicModuleNamesProvider() 
  5.     { 
  6.         var baseDirectory = AppContext.BaseDirectory; 
  7.  
  8.         var location = Path.Combine(baseDirectory, "modules"); 
  9.  
  10.         if (!Directory.Exists(location)) 
  11.         { 
  12.             return
  13.         } 
  14.  
  15.         foreach (var file in Directory.EnumerateFiles(location)) 
  16.         { 
  17.             var assemblyPath = Path.Combine(location, file); 
  18.  
  19.             var assembly = Assembly.LoadFrom(assemblyPath); 
  20.  
  21.             _moduleNames.AddRange(assembly.GetCustomAttributes<ModuleMarkerAttribute>().Select(m => m.Name)); 
  22.         } 
  23.     } 
  24.  
  25.     public IEnumerable<string> GetModuleNames() 
  26.     { 
  27.         return _moduleNames; 
  28.     } 

将其以单例形式注入,如下

  1. services.AddSingleton<IModuleNamesProvider, DynamicModuleNamesProvider>(); 

我们启动主项目验证确认,模块已然进行加载,如下:

但是访问控制器接口却显示404

并未继续深入查看源码,至少可知,通过动态加载内置仅仅只注册了相关服务,猜测是和移除对应视图包有关导致并未激活控制器、视图等等

OrchardCore动态加载模块激活控制器

由于控制器、视图、TagHelper等等相关FeatureProvider并未激活,所以我们借助AssemblyPart来实现,将其作为应用程序的一部分,通过扫描模块,将对应控制器等激活,如下:

  1. var builders = services.AddControllers(); 
  2.  
  3. builders.ConfigureApplicationPartManager(apm => 
  4.     var baseDirectory = AppContext.BaseDirectory; 
  5.  
  6.     var location = Path.Combine(baseDirectory, "modules"); 
  7.  
  8.     if (!Directory.Exists(location)) 
  9.     { 
  10.         return
  11.     } 
  12.  
  13.     foreach (var file in Directory.EnumerateFiles(location)) 
  14.     { 
  15.         var assemblyPath = Path.Combine(location, file); 
  16.  
  17.         var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); 
  18.  
  19.         var assemblyPart = new AssemblyPart(assembly); 
  20.  
  21.         apm.ApplicationParts.Add(assemblyPart); 
  22.     } 
  23. }); 

虽然官方并未提供动态加载模块示例,但我们依然可以借用其对外暴露接口来实现,理论上若是采用MVC模式,应该也可以进行动态加载

 

责任编辑:武晓燕 来源: JeffckyShare
相关推荐

2021-06-30 08:00:31

ECMAScriptimport 模块JavaScript

2022-07-20 11:13:05

前端JSONVue3

2017-06-09 08:16:50

python动态模块

2021-10-18 10:36:31

Spring Boot插件Jar

2021-10-18 12:04:22

Spring BootJava开发

2022-07-10 21:20:11

C语言Linux

2016-12-02 20:43:34

Android动态加载DL框架

2011-05-31 11:05:16

ListView 数据

2020-04-14 08:00:00

KubernetesLinux

2011-07-06 16:15:46

iPhone 图片

2024-02-29 07:45:38

Nginx服务模块

2020-07-16 07:50:53

Nginx模块动态

2011-06-24 09:01:20

Qt QLibrary dll

2009-08-28 16:14:26

C#实现加载动态库

2016-11-22 18:31:20

2015-11-02 19:11:27

阮一峰javascript循环加载

2011-07-25 15:32:06

iPhone Table 动态

2009-12-17 09:56:26

Linux添加驱动模块

2010-05-10 13:30:27

LTE战略SAMI模块

2011-07-21 17:35:11

iPhone Table 图片
点赞
收藏

51CTO技术栈公众号