前言

今天,我们再次讨论下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. NGK的发行量是多少?NGK销毁机制是怎么样的?

    代币销毁(Coin Burning),是指将代币从流通中永久性去除.换句话说,被销毁的代币相当于被永久性冻结,再也无法流入市场.那为什么要进行代币销毁呢? 销毁加密货币,可以使剩余加密货币的价值升高, ...

  2. NGK全球启动大会正式启动,资产上链的前景与机会在哪?

    据彭博社报道,加州时间11月25日,NGK全球启动大会在美国硅谷圆满落幕,本次NGK全球启动大会为NGK全球化进程正式拉开了帷幕. 众多业界人士共襄盛举,共同进行探讨未来公链发展的去向和契机. 当前, ...

  3. Baccarat项目专用代币BGV的价值如何?

    NGK投资者对于NGK平台自身的DeFi项目呼声越来越高,经过数月的紧张研发,检验和内测工作,NGK官方将于近日推出其去中心化金融项目--Baccarat,此项目为避免以太坊易被攻击,网络拥堵出块慢以 ...

  4. 谷歌地球服务器"失联"的替代方案

    2020年11月下旬,谷歌地球开始无法连接.作为谷歌地球的替代方案,推荐使用国产软件"图新地球LSV".网址 http://www.tuxingis.com 下载"图新地 ...

  5. MySQL 导入外部数据

    手工为数据库录入数据: 1 -- 使用数据库 2 use test; 3 4 -- 创建fruits数据表 5 create table fruits( 6 f_id char(10) not nul ...

  6. js---it笔记

    typeof a返回的是字符串 vscode scss安装的easy scss中的配置settingjson文件中的css编译生成路径是根目录下的

  7. 在 TKE 中使用 Velero 迁移复制集群资源

    概述 Velero(以前称为Heptio Ark)是一个开源工具,可以安全地备份和还原,执行灾难恢复以及迁移 Kubernetes 群集资源和持久卷,可以在 TKE 集群或自建 Kubernetes ...

  8. Vue学习笔记-vue-element-admin 按装报错再按装

    一  使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7  (Windows x86- ...

  9. 微信小程序:标签字符串直接变成标签来显示要通过富文本技术

    rich-text标签存在nodes属性直接接受标签字符串

  10. elasticsearch如何设计集群

    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 在写本文时就在想,如果让你负责一个elasticsearch集群,从零开始,你会从哪些方面 ...