OrchardCore实现模块化核心原理分析
共 2800字,需浏览 6分钟
·
2020-12-23 22:31
【导读】ABP vNext并未过多探究,当然其基于DDD理念分层清晰,灵活性、扩展性自然也不在话下,但有些情况下我可能会首选OrchardCore,并非ABP vNext不可
若改造项目,也因历史遗留问题,数据库表设计也可能存在不合理,此时从头开始再搭建如此庞大的架子,感觉会有点虚空,同时也要考虑团队内部情况,不是那么容易上手,反而可能会违背初心,花更多时间和精力在各种模型理解上
我们完全可以为后续做铺垫,先搭建出底层基本设施,再基于此做灵活扩展即可,每个公司项目具体情况都不一样,比如仓储模式可能需要结合项目进行对应 改造,仓储只是提供了一种基本思想,若真将网上普遍流传的模式照搬可能并不是那么好用,可能会认为仓储莫不是一种反模式
.NET Core模块化插件
.NET Core内置提供了AssemblyLoadContext加载dll插件方式实现模块化,然后将其进行注册
var mvcBuilder = services.AddMvc();
foreach (var module in modules)
{
// Register controller from modules
mvcBuilder.AddApplicationPart(module.Assembly);
}
这种方式虽可行,在我看来只能作为一种临时解决方案并不利于长期,因为需额外创建一个新的项目,然后加载所生成dll,由于没有底层设施做支撑,所以极易引起版本不一致问题,而且手动被迫性质太强,实现模块化方案最终的目标则只需关注业务逻辑实现,我们来看看OrchardCore如何实现模块化。
OrchardCore模块化思想
这里我们并不讨论和ABP vNext二者谁更强大,没有任何意义,比如需结合现有项目情况、项目大小、是否为多租户、实施难度等等多方面考虑才能得出基本结论,而不是一味追求当前主流
比如我们只是想实现模块化方案,建议选择OrchardCore来实施,因为很简单,我们可将其剥离为我所用,而后结合项目情况是否考虑利用ABP vNext来进行分层处理。借鉴核心思想、才能保证一切可在控制范围内
首先我们先从整体上对OrchardCore做个认识,细枝末节暂不考虑:基于ASP.NET Core多租户模块化应用框架。
版本管理:无论是底层设施、基本框架、模块都通过包管理,同时框架和包版本基本(包管理走框架包版本)可以统一管理(对于版本升级很重要)
核心思想:模块实现模块特性,通过MSBuild构建主程序所添加实现模块特性的模块包,底层设施扫描模块特性将其注册到容器中,当然模块和模块特性都可进行基本信息描述
OrchardCore模块化原理
整个项目架构如下图所示
OrchardCore:底层设施以及可能需要添加的组件(比如本地化、日志、文件存储、缓存、Lucene等)
OrchardCore.Frameworks:MVC框架
OrchardCore.Modules:模块化包(比如邮件服务、后台作业服务、第三方集成等等)
OrchardCore.Modules.Cms:Cms模块包
OrchardCore.Themes:主题管理
OrchardCore.Cms.Web:主程序
我以内置所提供示例程序给大家讲解整个详细流程,而后有需要更细致了解的童鞋就可以很快上手了,如下示例主程序加载示例模块,主程序直接采用引用该示例模块(实际则是通过nuget下载该模块)
正常情况下我们通过nuget直接下载的是程序包,而OrchardCore对于入口则是利用MSBuild加载targets文件(其他组件则直接下载对应包),而targets引用对应包,通过这种中转方式根据我的理解主要解决了两个问题,其一则是可以屏蔽底层设施包(一次性下载),最重要的是通过targets文件可自动添加主程序程序集所加载模块包特性
是不是感觉有点懵,那到底是如何加载模块包特性的呢?来,请看如下图,我们以实际操作从头再来做一个完整梳理(注意:为排版美观,如下都将省略OrchardCore前缀)
【1】创建Mvc.Web程序,在nuget上下载Application.Mvc.Targets包
【2】创建Mvc.HelloWorld模块,在nuget上下载引用Module.Targets包
【3】Mvc.Web主程序引用我们所使用的Mvc.HelloWorld模块
【4】Application.Mvc.Targets包引用Application.Targets(引入底层设施)和MVC.Core(引入MVC框架)
【5】示例模块引入模块包,该包中存在模块特性(Module类)
【6】Application.Targets包下存在Application.Targets.targets文件,由于主程序引用了该包,添加所引用实现模块特性的包程序集信息到主程序集
学习OrchardCore的前提一定要基本了解和会使用MSBuild,这里不详细展开,此时我们生成解决方案,我们将会看到主程序集里面将会自动生成所实现模块特性的模块程序集信息
到这里我们已经研究完主程序如何识别模块包,接下来则是如何加载模块包以及对应注册服务信息
OrcharCore核心在于OrchardCore和OrchardCore.Abstractions这两个底层设施包
归根到底,其底层设施源码一部分可能从官方源码拷贝过来(自我猜测),为实现多租户模式,势必要构建租户的容器和路由中间件,这中间就涉及在容器中需要维护每一个租户上下文(ShellContext),并且也要跟踪每个租户的状态。
ModularTenantContainerMiddleware作为创建租户容器中间件
ModularTenantRouterMiddleware作为租户路由中间件
网上资料一大把,此处省略若干字,有任何疑问可评论区留言,尽力解答
OrchardCore模块化实践
我将核心进行了剥离,实现了模块化的一个demo,将多租户这一块我也进行了去除,只保留了Shell相关基本概念,实际情况下,这些都可以去除,基于当前请求构建Scope,而无需再额外构建ShellScope和上下文等等,考虑好释放等问题就好
示例主程序为ModularDemo.Web.Test,模块为ModularCore.Test,启动主程序访问模块中接口