前言

今天,我们再次讨论下OrchardCore,通过初期调研,我们项目采用OrchardCore底层设施支持模块化,同时根据业务场景,额外还需支持二次开发,于是有了本文,若有不同解决方案,欢迎留言探讨

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

OrchardCore基本使用示例

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

项目采用前后分离,所以我们创建WebAPi应用程序,为支持模块化开发,如上图下载模块开发应用程序包,紧着在Startup文件中,添加OrchardCore服务以及使用其中间件,如下图

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

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

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

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

dotnet new ocmodulecms -n Test

由于我们用不到视图,所以将视图文件夹以及对应默认安装包删除,只需保留模块包【OrchardCore.Module.Targets】就好,同时也一并将项目文件中支持MVC配置给删除,否则会生成视图程序集,猜测应该会引起模块加载依赖需额外加载视图dll

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

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

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

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

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

查看底层模块设施源码,得知对外暴露其接口即IModuleNamesProvider,我们将生成模块dll放在主项目程序启动modules目录下,接下来我们实现该接口,如下:

public class DynamicModuleNamesProvider : IModuleNamesProvider
{
private readonly List<string> _moduleNames = new List<string>(); public DynamicModuleNamesProvider()
{
var baseDirectory = AppContext.BaseDirectory; var location = Path.Combine(baseDirectory, "modules"); if (!Directory.Exists(location))
{
return;
} foreach (var file in Directory.EnumerateFiles(location))
{
var assemblyPath = Path.Combine(location, file); var assembly = Assembly.LoadFrom(assemblyPath); _moduleNames.AddRange(assembly.GetCustomAttributes<ModuleMarkerAttribute>().Select(m => m.Name));
}
} public IEnumerable<string> GetModuleNames()
{
return _moduleNames;
}
}

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

services.AddSingleton<IModuleNamesProvider, DynamicModuleNamesProvider>();

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

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

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

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

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

var builders = services.AddControllers();

builders.ConfigureApplicationPartManager(apm =>
{
var baseDirectory = AppContext.BaseDirectory; var location = Path.Combine(baseDirectory, "modules"); if (!Directory.Exists(location))
{
return;
} foreach (var file in Directory.EnumerateFiles(location))
{
var assemblyPath = Path.Combine(location, file); var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); var assemblyPart = new AssemblyPart(assembly); apm.ApplicationParts.Add(assemblyPart);
}
});

总结

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

OrchardCore 如何动态加载模块?的更多相关文章

  1. stevedore动态加载模块

    stevedore动态加载模块,stevedore使用setuptools的entry points来定义并加载插件.entry point引用的是定义在模块中的对象,比如类.函数.实例等,只要在im ...

  2. Python_getattr+__import__ 实现动态加载模块、类对象或函数

    __import__() 语法 __import__(name[, globals[, locals[, fromlist[, level]]]]) 参数 name -- 字符串,模块的导入路径 说明 ...

  3. AngularJs 动态加载模块和依赖

    最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...

  4. [driver]linux内核动态加载模块

    问题: 1. 把编译好的模块放到板子/lib/modules对应文件夹下,并且执行了depmod -a, 比如pl2303.ko, 那么下一次插入pl2303的串口线,是否可以识别,也就是自动加载pl ...

  5. angular-ui-router动态加载模块

    1.定义index.html主页,对于通用的js就不用require依赖加载了,其中main.js作为主模块,用require添加系统路由模块. <!DOCTYPE html> <h ...

  6. nginx平滑升级、在线添加模块(tengine 动态加载模块)

    http://www.orzace.com/how-to-upgrade-nginx/ 下面是nginx替换成tengine再加上lua 模块,(tengine-2.0.1版本暂时无法动态加载lua模 ...

  7. Apache动态加载模块

    添加步骤:如要额外安装cgi,先找到mod_cgi.c及mod_cgid.c.一般在apache安装包目录下,如 ./httpd-2.2.25/modules/generators .#编译安装 cg ...

  8. ubuntu动态加载模块简单模板

    1:简单代码 #include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("GPL"); ...

  9. 配置动态加载模块和js分模块打包,生产环境和开发环境公共常量配置

    1. 话不多少 先上代码:  route.js  // 引用模板 分模块编译 const main = r => require.ensure([], () => r(require('. ...

随机推荐

  1. Vue3组件(九)Vue + element-Plus + json = 动态渲染的表单控件

    一个成熟的表单 表单表单,你已经长大了,你要学会: 动态渲染 支持单列.双列.多列 支持调整布局 支持表单验证 支持调整排列(显示)顺序 依据组件值显示需要的组件 支持 item 扩展组件 可以自动创 ...

  2. 面试必知:String、StringBuilder、StringBuffer的区别

    你知道String.StringBuilder.Stringbuffer的区别吗?当你创建字符串的时候,有考虑过该使用哪个吗? 别急,这篇文章带你解决这些问题. 可变性 首先,String是字符串,我 ...

  3. Bootstrap下拉菜单、按钮式下拉菜单

    1. 概述 下拉菜单使用频率也是比较高的,比较常见的使用场景是在导航菜单栏,某个主菜单含有下拉的子菜单. Bootstrap为下拉菜单提供了两种实现方式,即普通的下拉菜单还有按钮式的下拉菜单.我们先看 ...

  4. 后端程序员之路 32、Index搜索引擎实现分析1-类的设计

    # 1.forward_index 正排索引(正向索引)- filter_t- filter_judge # 2.inverted_index 倒排索引(反向索引)- inverted_pre_sco ...

  5. 通过golang小案例,了解golang程序常见机制

    目录 代码理解及纠错 1.defer和panic执行先后顺序 2.for循环元素副本问题 3.slice追加元素问题 4.返回值命名问题 5.用new初始化内置类型问题 6.切片append另外一个切 ...

  6. 微信小程序 下拉刷新 上拉加载

    1.下拉刷新  小程序页面集成了下拉功能,并提供了接口,我们只需要一些配置就可以拿到事件的回调. 1. 需要在 .json 文件中配置. 如果配置在app.json文件中,那么整个程序都可以下拉刷新. ...

  7. 腾讯云容器服务 TKE 拿下新加坡 MTCS 最高级别安全认证

    近日,腾讯云容器服务 TKE 荣获新加坡 MTCS 最高级安全认证,标志着腾讯云 TKE 在为用户提供可靠.易部署.灵活扩展等基础服务上,已经全面满足了新加坡监管机构以及多个行业客户对服务安全的要求. ...

  8. 记录PHP post提交表单导入mysql中文乱码的问题

    记录记录PHP post提交表单导入mysql中文乱码的问题 关于乱码,这是个糟糕的问题!涉及到很多地方 解决思路:程序所涉及的环境字符集不一致导致 mysql出现乱码一般是mysql数据库内部的字符 ...

  9. 泛微OA 多版本存在命令执行

    参考 https://blog.csdn.net/qq_41770175/article/details/102821349 https://www.linktrust.net/oday/471.ht ...

  10. 解决图片把父元素向下撑大大约3px问题

    现象  bug: 图片在div\li\dt 等  图片把父元素向下撑大大约3px  <style>         img {             width: 30%; //这里由于 ...