前言

今天,我们再次讨论下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. 08.手写KNN算法测试

    导入库 import numpy as np from sklearn import datasets import matplotlib.pyplot as plt 导入数据 iris = data ...

  2. Mysql的join算法

    本文转载自Mysql的join算法 导语 在Mysql中,使用Nested-Loop Join的算法思想去优化join,Nested-Loop Join翻译成中文则是"嵌套循环连接" ...

  3. 处理ios键盘弹出按钮点击click失效

    用ontouchstart绑定事件即可,然后用 document.activeElement.blur();让键盘收起 this.value = value.replace(/\s/g, " ...

  4. Vue学习笔记-Windows系统Git安装(按装vue-element-admin报错)

    一  使用环境: windows 7 64位操作系统 二  Windows系统Git安装(Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理,是目前使用范围最广的版 ...

  5. SpringBoot(九):SpringBoot集成Mybatis

    (1)新建一个SpringBoot工程,在pom.xml中配置相关jar依赖 贴代码: <!--加载mybatis整合springboot--> <dependency> &l ...

  6. es6 快速入门 系列

    es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...

  7. Docker 下Elasticsearch 的安装 和ik分词器

    (1)docker镜像下载 docker pull elasticsearch:5.6.8 (2)安装es容器 docker run -di --name=changgou_elasticsearch ...

  8. 微信小程序左滑删除

    <view class="touch-item {{item.isTouchMove ? 'touch-move-active' : ''}}" data-index=&qu ...

  9. 【资源下载】Linux下的Hi3861一站式鸿蒙开发烧录(附工具)

    下载附件 2021春节前夕,华为发布了 HUAWEI DevEco Device Tool 2.0 Beta1,整体提供了异常强大的功能.得知消息后,我在第一时间带着无比兴奋的心情下载尝鲜,但结果却是 ...

  10. PTA甲级—数学

    1.简单数学 1008 Elevator (20分) 模拟题 #include <cstdio> #include <cstring> #include <string& ...