当前位置: 首页 > 科技观察

OrchardCore是如何动态加载模块的?

时间:2023-03-12 10:40:03 科技观察

本文转载自微信公众号“JeffckyShare”,作者Jeffcky。转载请联系JeffckyShare公众号.了解OrchardCore的童鞋应该知道,OrchardCore本身定位于CMS系统,整个架构前后端不分离,采用MVC模式开发。基于此,由于需要预编译视图等原因,不支持动态加载。Modules,本文给出OrchardCore的基本使用示例,我想到的动态加载模块方案。OrchardCore使用包来管理各个模块,所以有一个自建的NuGet。我们提前配置了OrchardCore包源项目,实现了前后台分离,所以我们创建了一个WebAPI应用。为了支持模块化开发,下载如上图所示的模块开发应用包放在Startup文件中,添加OrchardCore服务并使用其中间件,如下图,至此一个基本的模块化项目是创建好了,然后我们创建模块,官方提供模块包模板引擎,下载模板引擎到本地dotnetnew-iOrchardCore.ProjectTemplates::1.0.0-rc2-16113--nuget-sourcehttps://nuget.cloudsmith.io/orchardcore/preview/v3/index通过相应的命令。json然后我们继续在项目解决方案下通过CLI将其下载到本地模板引擎创建一个模块项目,在项目解决方案中引入dotnetnewocmodulecms-nTest由于我们不用视图,视图文件夹和删除相应的默认安装包,只保留下面的模块包OrchardCore.Module.Targets,同时删除项目文件中支持MVC的配置,否则会生成视图程序集,猜测应该是模块加载依赖导致额外加载视图dll。我们将模块默认的创建控制器改为访问接口形式,方便接下来的测试验证。那我们应该如何加载开发好的模块呢?OrchardCore动态加载模块(前后分离)。我们应该知道OrchardCore的基本原理,默认情况下,主工程添加模块引用时,会通过MSBuild将模块ID添加到对应的模块程序集中,如下:如上图所示,一个是模块ID,另一个是对应的文件路径ID。启动主工程时,对应的Assembly模块识别、注册服务等操作,貌似只需要了解源码中是否有存储对应模块信息的接口即可?查看底层模块设施源码,得知其对外暴露接口,即IModuleNamesProvider。我们将生成模块dll放在主工程程序启动模块目录下,然后我们实现接口如下:varlocation=Path.Combine(baseDirectory,"modules");if(!Directory.Exists(location)){return;}foreach(varfileinDirectory.EnumerateFiles(location)){varassemblyPath=Path.Combine(location,file);varassembly=集会。LoadFrom(assemblyPath);_moduleNames.AddRange(assembly.GetCustomAttributes().Select(m=>m.Name));}}publicIEnumerableGetModuleNames(){return_moduleNames;}}将其作为单例注入,如遵循services.AddSingleton();我们启动主工程验证,确认模块已经加载,如下:但是门禁控制器界面显示404,没有继续看源码。至少我们可以看到内置的只有通过动态加载才注册相关服务。猜测是和相应视图包的移除有关。结果,控制器,视图等没有被激活。AssemblyPart,作为应用程序的一部分,通过扫描模块,将对应controller的激活如下:存在(位置)){返回;}foreach(varfileinDirectory.EnumerateFiles(位置)){varassemblyPath=Path.Combine(位置,文件);varassembly=AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);varassemblyPart=newAssemblyPart(程序集);apm。ApplicationPartsAdd(assemblyPart);}});虽然官方没有提供动态加载模块的例子,但是我们还是可以通过它对外暴露的接口来实现的。理论上,如果采用MVC模型,动态加载应该也是可以的