OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0
开发的一个.NetCore
快速开发框架。这个框架使用最新稳定版的.NetCore SDK
(当前是.NET Core 2.2),对 AspNetCore 的配置、依赖注入、日志、缓存、实体框架、Mvc(WebApi)、身份认证、权限授权等模块进行更高一级的自动化封装,并规范了一套业务实现的代码结构与操作流程,使 .Net Core 框架更易于应用到实际项目开发中。
开源地址:https://github.com/i66soft/osharp
官方示例:https://www.osharp.org
文档中心:https://docs.osharp.org
VS 插件:https://marketplace.visualstudio.com/items?itemName=LiuliuSoft.osharp
框架的工程组织结构如下:
OSharp【框架核心组件】:框架的核心组件,包含一系列快速开发中经常用到的Utility辅助工具功能,框架各个组件的核心接口定义,部分核心功能的实现
OSharp.AspNetCore【AspNetCore组件】:AspNetCore组件,提供AspNetCore的服务端功能的封装
OSharp.AutoMapper【对象映射组件】:AutoMapper 对象映射组件,封装基于AutoMapper的对象映射实现
OSharp.EntityFrameworkCore【EFCore 数据组件】:EFCore数据访问组件,封装EntityFrameworkCore数据访问功能的实现
OSharp.EntityFrameworkCore.MySql【EFCore MySql 数据组件】:EFCore MySql数据访问组件,封装MySql的EntityFrameworkCore数据访问功能的实现
OSharp.EntityFrameworkCore.SqlServer【EFCore SqlServer 数据组件】:EFCore SqlServer数据访问组件,封装SqlServer的EntityFrameworkCore数据访问功能的实现
OSharp.EntityFrameworkCore.Sqlite【EFCore Sqlite 数据组件】:EFCore Sqlite数据访问组件,封装Sqlite的EntityFrameworkCore数据访问功能的实现
OSharp.EntityFrameworkCore.PostgreSql【EFCore PostgreSql 数据组件】:EFCore PostgreSql数据访问组件,封装PostgreSql的EntityFrameworkCore数据访问功能的实现
OSharp.EntityFrameworkCore.Oracle【EFCore PostgreSql 数据组件】:EFCore Oracle数据访问组件,封装Oracle的EntityFrameworkCore数据访问功能的实现
OSharp.Permissions【权限组件】:使用AspNetCore的Identity为基础实现身份认证的封装,以Security为基础实现以角色-功能、用户-功能的功能权限实现,以角色-数据,用户-数据的数据权限的封装
OSharp.Log4Net【日志组件】:基于Log4Net的日志记录组件
OSharp.Redis【缓存组件】:基于Redis的分布式缓存客户端组件
OSharp.Hangfire【后台任务组件】:封装基于Hangfire后台任务的服务端实现
OSharp.MiniProfiler【MiniProfiler组件】:基于MiniProfiler实现的性能监测组件
OSharp.Swagger【SwaggerAPI组件】:基于Swagger生成MVC的Action的API测试接口信息
OSharp.Exceptionless【Exceptionless分布式日志组件】:封装基于Exceptionless 分布式日志记录实现
OSharp框架设计了一个模块(Pack)系统,每个Pack以一个实现了模块基类(OsharpPack)的类作为入口,这个类完成本模块的服务添加(AddService)和模块初始化工作(UserPack)。一个Pack是一系列高内聚低耦合的服务组织,对象提供一个功能(如缓存功能,日志功能,数据存储功能)或完成一组业务处理(如身份认证,权限授权)。
一个Pack入口类的代码如下:
public class XXXPack : OsharpPack
{
public override PackLevel Level => PackLevel.Core;
public override int Order => 2;
public override IServiceCollection AddServices(IServiceCollection services)
{
return services;
}
public override void UsePack(IServiceProvider provider)
{
IsEnabled = true;
}
}
当前框架的模块组成如下图:
OSharp核心模块 | OSharp.Core.Packs.OsharpCorePack | Core |
依赖注入模块 | OSharp.Dependency.DependencyPack | Core |
Log4Net模块 | OSharp.Log4Net.Log4NetPack | Core |
AspNetCore模块 | OSharp.AspNetCore.AspNetCorePack | Core |
事件总线模块 | OSharp.EventBuses.EventBusPack | Core |
AutoMapper模块 | OSharp.AutoMapper.AutoMapperPack | Framework |
Hangfire后台任务模块 | OSharp.Hangfire.HangfirePack | Framework |
Redis模块 | OSharp.Redis.RedisPack | Framework |
MySqlEntityFrameworkCore模块 | OSharp.Entity.MySql.MySqlEntityFrameworkCorePack | Framework |
SqliteEntityFrameworkCore模块 | OSharp.Entity.Sqlite.SqliteEntityFrameworkCorePack | Framework |
SqlServerEntityFrameworkCore模块 | OSharp.Entity.SqlServer.SqlServerEntityFrameworkCorePack | Framework |
SqlServer-DefaultDbContext迁移模块 | OSharp.Site.Web.Startups.SqlServerDefaultDbContextMigrationPack | Framework |
MVC功能点模块 | OSharp.AspNetCore.Mvc.MvcFunctionPack | Application |
数据实体模块 | OSharp.Core.EntityInfos.EntityInfoPack | Application |
系统信息模块 | OSharp.Systems.SystemPack | Application |
身份认证模块 | OSharp.Site.Identity.IdentityPack | Application |
MVC模块 | OSharp.Site.Web.Startups.AspNetCoreMvcPack | Application |
SignalR模块 | OSharp.Site.Web.Startups.SignalRPack | Application |
权限安全模块 | OSharp.Site.Security.SecurityPack | Application |
代码生成模块 | OSharp.Site.Web.Startups.CodeGeneratorPack | Application |
SwaggerApi模块 | OSharp.Swagger.SwaggerPack | Application |
审计模块 | OSharp.Site.Systems.AuditPack | Application |
框架定义了ISingletonDependency,IScopeDependency,ITransientDependency 三个空接口,对应着依赖注入的ServiceLifetime.Singleton
、ServiceLifetime.Scoped
、ServiceLifetime.Transient
三种服务生命周期。按需要实现了空接口的服务类,将在系统初始化时被检索出来进行实现类与其接口的依赖注入服务注册。
空接口的标注方式,统一使用TryAdd来进行注入
一个示例代码如下:
public XXXService : IXXXService, ISingletonDependency
{ }
这个示例代码将在系统初始化时执行如下的注入行为:
services.TryAdd(new ServiceDescriptor(typeof(IXXXService),
typeof(XXXService), ServiceLifetime.Singleton));
空接口的标注方式,只能指定服务的注册生命周期类型,而不能进行更多的配置,因此增加了[Dependency]特性的标注方式。通过[Dependency]
,可以进行 服务注册的生命周期类型、是否是TryAdd方式注册、是否替换已存在的服务、是否注册自身 等配置,使用起来更加灵活方便。
一个示例代码如下:
[Dependency(ServiceLifetime.Singleton, ReplaceExisting = true, AddSelf = true)]
public XXXService : IXXXService
{ }
这个示例代码将在系统初始化时执行如下的注入行为:
services.Replace(new ServiceDescriptor(typeof(IXXXService),
typeof(XXXService), ServiceLifetime.Singleton));
services.TryAdd(new ServiceDescriptor(typeof(XXXService),
typeof(XXXService), ServiceLifetime.Singleton));
系统初始化时,通过反射检索程序集的方式,检索出所有服务类型(ServiceType)与服务实现(ImplementationType)及生命周期类型(ServiceLifetime)的相关数据,将依赖注入服务注册到服务容器ServiceCollection
中。
数据模块使用了UnitOfWork-Repository的模式来设计,设计了一个泛型的实体仓储接口IRepository
基于MVC的ActionFilter的UnitOfWorkAttribute AOP 事务自动提交,业务中不再需要关心事务的生命周期。
系统初始化时,通过反射检索程序集的方式,检索出各个实体与上下文的映射关系,向上下文中动态添加实体类来构建上下文类型,以达到上下文类型与业务实体解耦的目的。通过统一基类EntityTypeConfigurationBase
使用AspNetCore原生的用户身份认证框架,身份认证相关操作统一使用UserManager
,RoleMamanger两个入口,保持了原生Identity的体系强大性与功能完整性。重新设计了用户存储UserStore和角色存储RoleStore,使用框架内设计的IRepository
从底层开始,自动收集了系统的所有业务点(IFunction)和数据实体(IEntityInfo),用于对系统的功能权限、数据权限、数据缓存、操作审计 等实用功能提供数据支持。
功能点Function
与MVC的Area/Controller/Action
一一对应,是功能权限的最小验证单位,基于功能点,可以配置:
功能访问类型(匿名访问、登录访问、限定角色访问)
功能的数据缓存时间及缓存过期方式(绝对过期、相对过期)
是否开启操作审计(XXX人员XXX时间做了XXX操作)
是否开启数据审计(操作引起的数据变化详情(新增、更新、删除))
数据实体EntityInfo
与数据库中的各个数据实体一一对应,基于数据实体,可以配置:
是否开启数据审计,与Function
上的同配置级别不同,如果指定实体未开放审计,则不审计当前实体。
实现数据权限,基于角色 - 实体
的数据权限设计,通过配置实现 XXX角色是否有权访问XXX实体数据(的XX属性)
设计了一个树形结构的业务模块体系(Module),对应着后端向前端(菜单/按钮)开放的API,一个模块可由一个或多个功能点构成,模块是对外开放的特殊功能点,是进行 角色/用户功能授权 的单位。把一个模块授权给角色,角色即拥有了一个或多个功能点的操作权限。
系统初始化时,根据每个角色Role
分配到的模块Module
,自动初始化每个 角色 Role - Function[]
的权限对应关系并缓存
游客进入系统时,自动请求所有可匿名访问FunctionAccessType.Anonymouse
的模块信息并缓存到浏览器,浏览器根据这个缓存的模块集合,对前端页面的各个操作点(菜单/按钮)进行是否隐藏/禁用的状态控制
注册用户登录系统时,自动请求所有可执行(包括匿名的FunctionAccessType.Anonymouse
、登录的FunctionAccessType.Logined
、指定角色的FunctionAccessType.RoleLimit
)的模块信息并缓存到浏览器,浏览器根据这个缓存的模块集合,对前端页面的各个操作点(菜单/按钮)进行是否隐藏/禁用的状态控制
用户User
执行一个功能点Function
时,验证流程如下:
用户未登录,返回401
逐个验证用户拥有的角色Role
,根据角色从缓存中取出Role-Function[]
缓存项,Function[]
包含要验证的功能点时,验证通过
由分配给用户的模块Module
对应的功能点,获取到User-Function[]
(并缓存),Function[]
包含要验证的功能点时,验证通过
验证未通过,返回403
功能点不存在时,返回404
功能点被锁定时,返回423
功能点可访问性为匿名FunctionAccessType.Anonymouse
验证通过
功能点可访问性为需要登录FunctionAccessType.Logined
时,用户未登录,返回401,已登录则验证通过
功能点可访问性为需要登录FunctionAccessType.RoleLimit
时,流程如下:
基于 角色Role
-实体EntityInfo
的一一对应关系,配置指定角色对指定数据实体的数据查询筛选规则,并持久化到数据库中
数据查询筛选规则组成为 条件组FilterGroup
和条件FilterRule
,一个条件组 FilterGroup 包含 一个或多个条件 FilterRule 和 一个或多个 条件组FilterGroup
,这样就实现了条件组和条件的无限嵌套,能满足绝大多数数据筛选规则的组装需要,如下图:
系统初始化时,将所有角色-实体
的数据筛选规则缓存到内存中
进行数据查询的时候,根据当前用户的所有角色 Role
和要查询的实体 EntityInfo
,查找出所有配置的数据筛选规则FilterGroup
,转换为数据查询表达式Expression
,各个角色的表达式之间使用Or
逻辑进行组合
将以上生成的数据权限
数据查询表达式,使用And
逻辑组合到用户的提交的查询条件生成的表达式中,得到最终的数据查询表达式,提交到数据库中进行数据查询,从而获得数据权限限制下的合法数据
OSharp 快速启动模板的开发模式,集成了Swagger
API 文档生成组件,更方便了前后端分离的开发模式中前后端开发人员的数据接口对接工作。基于Swagger
的工作原理,API的输入输出都需使用强类型
的数据类型,Swagger
才能发挥更好的作用,而OSharp框架通过AutoMapper
的ProjectTo
对业务实体到输出DTOIOutputDto
提供了自动映射功能,能有效减轻后端开发中数据对象属性映射的工作量。
OSharp 的这个版本是基于Angular前端框架 NG-ALAIN 开发的,部分界面展示如下:
原文地址:https://www.cnblogs.com/guomingfeng/p/osharpns-intro.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com