【愚公系列】2023年03月 MES生产制造执行系统-001.Autofac的使用

举报
愚公搬代码 发表于 2023/04/30 23:28:35 2023/04/30
【摘要】 前言IoC容器是一种设计模式,它可以管理应用程序中的对象依赖关系。它可以自动创建和注入对象,从而减少了代码的耦合度和重复性。Autofac是Microsoft .NET的IoC容器。它管理类之间的依赖关系,以便应用程序在大小和复杂性增加时易于更改。这是通过将常规 .NET 类视为组件来实现的。Autofac的官网:https://autofac.org/ Autofac的源码网址:https...

前言

IoC容器是一种设计模式,它可以管理应用程序中的对象依赖关系。它可以自动创建和注入对象,从而减少了代码的耦合度和重复性。

Autofac是Microsoft .NET的IoC容器。它管理类之间的依赖关系,以便应用程序在大小和复杂性增加时易于更改。这是通过将常规 .NET 类视为组件来实现的。

Autofac的官网:https://autofac.org/

Autofac的源码网址:https://gitee.com/dennisdyh/Autofac.Extensions.DependencyInjection

一、Autofac的使用

1.安装包

Autofac.Extensions.DependencyInjection


2.服务注入

在Program注入Autofac服务

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.Limits.MaxRequestBodySize = 10485760;
// Set properties and call methods on options
});
webBuilder.UseKestrel().UseUrls("http://*:9991");
webBuilder.UseIIS();
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(new AutofacServiceProviderFactory());//设置工厂来替换实例


在Startup中增加ConfigureContainer方法,用来配置映射关系

public void ConfigureContainer(ContainerBuilder builder)
{
Services.AddModule(builder, Configuration);
}

使用了Autofac以后,在IServiceCollection中注入的服务,也能生效;因为Autofac是先接受了所有的来自于IServiceCollection的服务映射后,再去读取ConfigureContainer方法中配置的映射。

3.AddModule扩展方法详解

AddModule包含了反射注入容器和一堆服务注入容器

// private static bool _isMysql = false;
public static IServiceCollection AddModule(this IServiceCollection services, ContainerBuilder builder, IConfiguration configuration)
{
//services.AddSession();
//services.AddMemoryCache();
//初始化配置文件
AppSetting.Init(services, configuration);
Type baseType = typeof(IDependency);
var compilationLibrary = DependencyContext.Default
.RuntimeLibraries
.Where(x => !x.Serviceable
&& x.Type == "project")
.ToList();
var count1 = compilationLibrary.Count;
List<Assembly> assemblyList = new List<Assembly>();

foreach (var _compilation in compilationLibrary)
{
try
{
assemblyList.Add(AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(_compilation.Name)));
}
catch (Exception ex)
{
Console.WriteLine(_compilation.Name + ex.Message);
}
}
builder.RegisterAssemblyTypes(assemblyList.ToArray())
.Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
.AsSelf().AsImplementedInterfaces()
.InstancePerLifetimeScope();
builder.RegisterType<UserContext>().InstancePerLifetimeScope();
builder.RegisterType<ActionObserver>().InstancePerLifetimeScope();
//model校验结果
builder.RegisterType<ObjectModelValidatorState>().InstancePerLifetimeScope();
string connectionString = DBServerProvider.GetConnectionString(null);

if (DBType.Name == DbCurrentType.MySql.ToString())
{
//增加dapper对mysql字段Guid映射
SqlMapper.AddTypeHandler(new DapperParseGuidTypeHandler());
SqlMapper.RemoveTypeMap(typeof(Guid?));

//services.AddDbContext<SysDbContext>();
//mysql8.x的版本使用Pomelo.EntityFrameworkCore.MySql 3.1会产生异常,需要在字符串连接上添加allowPublicKeyRetrieval=true
services.AddDbContextPool<SysDbContext>(optionsBuilder => { optionsBuilder.UseMySql(connectionString); }, 64);
services.AddDbContextPool<ServiceDbContext>(optionsBuilder => { optionsBuilder.UseMySql(connectionString); }, 64);
services.AddDbContextPool<ReportDbContext>(optionsBuilder => { optionsBuilder.UseMySql(connectionString); }, 64);
}
else if (DBType.Name == DbCurrentType.PgSql.ToString())
{
services.AddDbContextPool<SysDbContext>(optionsBuilder => { optionsBuilder.UseNpgsql(connectionString); }, 64);
services.AddDbContextPool<ServiceDbContext>(optionsBuilder => { optionsBuilder.UseNpgsql(connectionString); }, 64);
services.AddDbContextPool<ReportDbContext>(optionsBuilder => { optionsBuilder.UseNpgsql(connectionString); }, 64);
}
else
{
services.AddDbContextPool<SysDbContext>(optionsBuilder => { optionsBuilder.UseSqlServer(connectionString); }, 64);
services.AddDbContextPool<ServiceDbContext>(optionsBuilder => { optionsBuilder.UseSqlServer(connectionString); }, 64);
services.AddDbContextPool<ReportDbContext>(optionsBuilder => { optionsBuilder.UseSqlServer(connectionString); }, 64);
}
//启用缓存
if (AppSetting.UseRedis)
{
builder.RegisterType<RedisCacheService>().As<ICacheService>().SingleInstance();
}
else
{
builder.RegisterType<MemoryCacheService>().As<ICacheService>().SingleInstance();
}
//kafka注入
//if (AppSetting.Kafka.UseConsumer)
// builder.RegisterType<KafkaConsumer<string, string>>().As<IKafkaConsumer<string, string>>().SingleInstance();
//if (AppSetting.Kafka.UseProducer)
// builder.RegisterType<KafkaProducer<string, string>>().As<IKafkaProducer<string, string>>().SingleInstance();
return services;
}


3.1 AppSetting.Init

应用程序初始化主要是对配置文件使用

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"VirtualPath": {
"StaticFile": "E:\\Web\\Static", //配置的虚拟目录文件所在路径
"FolderName": "/Static" //访问时此路径时的别名
},
"AppUrls": {
},
"Connection": {
"DBType": "MsSql", //MySql/MsSql/PgSql //数据库类型,如果使用的是sqlserver此处应设置为MsSql
//sqlserver连接字符串
"DbConnectionString": "Data Source=.;Initial Catalog=iMES_Open;Persist Security Info=True;User ID=sa;Password=1;Connect Timeout=500;",

//mysql连接字符串(升级EFCore3.1到时已将mysql连接字符串修改,2019-12-20)
//"DbConnectionString": " Data Source=127.0.0.1;Database=imes_open;AllowLoadLocalInfile=true;User ID=root;Password=123456;allowPublicKeyRetrieval=true;pooling=true;CharSet=utf8;port=3306;sslmode=none;",

//PgSql连接字符串
// "DbConnectionString": "Host=132.232.2.109;Port=5432;User id=postgres;password=jxx_abcd;Database=netcoredev;",
"RedisConnectionString": "127.0.0.1,Password=123456,SyncTimeout=15000", //redis连接字符串(最好加密)
"UseRedis": "false", //是否使用redis,如果不使用,默认使用Memory内置缓存
"UseSignalR": "true" //是否使用SignalR(2022.05.03),注意需要将端的地址配置到下面的CorsUrls属性中
},
//业务数据库连接
"ServiceConnectingString": "Data Source=.;Initial Catalog=iMES;Persist Security Info=True;User ID=sa;Password=123456;Connect Timeout=500;",
//报表数据库连接
"ReportConnectingString": "Data Source=.;Initial Catalog=iMES;Persist Security Info=True;User ID=sa;Password=123456;Connect Timeout=500;",
"Secret": { //秘钥配置
"JWT": "BB3647441FFA4B5DB4E64A29B53CE525", //JWT
"Audience": "iMES.core",
"Issuer": "iMES.core.owner",
"User": "C5ABA9E202D94C43A3CA66002BF77FAF", //
"DB": "3F8B7B38AD3D484A89ACA513CBD79F36",
"Redis": "E6D90DDBC70C4F4EA3C312B6FCB473C8"
},
//================跨域请求 (CORS)配置(2019-12-20新增),
//================.netcore3.1必须配置此属性,多个url用豆号隔开,url为vue站点的地址,可以将发布后的地址也同时配置上
"CorsUrls": "http://localhost:8081,http://localhost:8082,http://localhost:8080,http://localhost:7080,http://localhost:9980,http://127.0.0.1:9980,http://localhost:9990,http://www.volcore.xyz,http://app.625sc.com,https://imes.625sc.com",
"ExpMinutes": "120", //JWT有效期(分钟=默认120),
"CreateMember": { //对表插入数据时,需要记录创建人/创建时间/创建日期,配置UserIdField/UserNameField/DateField分别为对应数据库的创建人CreateID,创建人Creator,创建时间CreateDate字段(新建数据时,由框架默认完成给这几个字段赋值,字段区分大小写)或可手动调用T.SetCreateDefaultVal()完成设置创建人/创建时间/创建日期
//如果表的主键是GUID,界面查询时默认会用到DateField对应的实体(数据库)字段进行排序
"UserIdField": "CreateID",
"UserNameField": "Creator",
"DateField": "CreateDate"
},
"ModifyMember": { //修改同上
"UserIdField": "ModifyID",
"UserNameField": "Modifier",
"DateField": "ModifyDate"
}, //演示系统过滤Action,只有超级管理员才能操作,其他用户只有只读权限
"GlobalFilter": {
"Message": "演示环境,当前帐号没有开启此功能权限",
"Enable": "false", //开启Action过滤
"Actions": [ "Update", "Del", "Add", "SavePermission", "Save", "CreatePage", "CreateVuePage", "CreateEntityModel", "SaveEidt", "CreateServices", "Import", "Upload", "Audit", "ModifyPwd" ]
},
"Kafka": {
//是否使用生产者
"UseProducer": false,
"ProducerSettings": {
"BootstrapServers": "192.168.20.241:9092", //confluent cloud bootstrap servers
"SaslMechanism": "Plain",
"SecurityProtocol": "SaslSsl",
"SaslUsername": "<confluent cloud key>",
"SaslPassword": "<confluent cloud secret>"
},
//是否使用消费者
"UseConsumer": false,
//是否持续监听消费者订阅 用于while循环订阅
"IsConsumerSubscribe": true,
"ConsumerSettings": {
"BootstrapServers": "192.168.20.241:9092", //confluent cloud bootstrap servers
"GroupId": "amcl_group", //web-example-group
"SaslMechanism": "Plain",
"SecurityProtocol": "SaslSsl",
"SaslUsername": "<confluent cloud key>",
"SaslPassword": "<confluent cloud secret>"
},
"Topics": {
"TestTopic": "alarm_topic"
}
},
"Mail": {
"Address": "zm_rid@163.com", //发件的邮箱
"Host": "smtp.163.com",
"Name": "iMES", //发送人名称
"Port": 25,
"EnableSsl": false,
"AuthPwd": "授权密码" //授权密码(对应邮箱设置里面去开启)
},
"QuartzAccessKey": "65EC9387312E4717810C552963CE59FF", //定时任务的值
"ExportPDFPath": "C:\\iMES_Open\\iMES_Front\\PDF" //导出PDF路径
}


public static void Init(IServiceCollection services, IConfiguration configuration)
{
//---------------------------------配置信息服务类的映射------------------------------
Configuration = configuration;
services.Configure<Secret>(configuration.GetSection("Secret"));
services.Configure<Connection>(configuration.GetSection("Connection"));
services.Configure<CreateMember>(configuration.GetSection("CreateMember"));
services.Configure<ModifyMember>(configuration.GetSection("ModifyMember"));
services.Configure<GlobalFilter>(configuration.GetSection("GlobalFilter"));
services.Configure<Kafka>(configuration.GetSection("Kafka"));
//---------------------------------获取当前程序目录-----------------------------------
var provider = services.BuildServiceProvider();
IWebHostEnvironment environment = provider.GetRequiredService<IWebHostEnvironment>();
CurrentPath = Path.Combine(environment.ContentRootPath, "").ReplacePath();
//---------------------------------获取各种配置操作类-------------------------------------
Secret = provider.GetRequiredService<IOptions<Secret>>().Value;

//设置修改或删除时需要设置为默认用户信息的字段
CreateMember = provider.GetRequiredService<IOptions<CreateMember>>().Value ?? new CreateMember();
ModifyMember = provider.GetRequiredService<IOptions<ModifyMember>>().Value ?? new ModifyMember();
//全局过滤行为
GlobalFilter = provider.GetRequiredService<IOptions<GlobalFilter>>().Value ?? new GlobalFilter();

GlobalFilter.Actions = GlobalFilter.Actions ?? new string[0];
//Kafka消息队列
Kafka = provider.GetRequiredService<IOptions<Kafka>>().Value ?? new Kafka();
//各种数据库和缓存数据库连接字符串
_connection = provider.GetRequiredService<IOptions<Connection>>().Value;
//JWT过期时间
ExpMinutes = (configuration["ExpMinutes"] ?? "120").GetInt();

//判断数据库是否存在
DBType.Name = _connection.DBType;
if (string.IsNullOrEmpty(_connection.DbConnectionString))
throw new System.Exception("未配置好数据库默认连接");
//进行数据库解密(解密失败返回原字符串,成功返回新字符串)
try
{
_connection.DbConnectionString = _connection.DbConnectionString.DecryptDES(Secret.DB);
}
catch { }

if (!string.IsNullOrEmpty(_connection.RedisConnectionString))
{
try
{
_connection.RedisConnectionString = _connection.RedisConnectionString.DecryptDES(Secret.Redis);
}
catch { }
}

}


3.1.1 数据库字符串加/解密

public static class SecurityEncDecryptExtensions
{

private static byte[] Keys = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
/// <summary>
/// DES加密字符串
/// </summary>
/// <param name="encryptString">待加密的字符串</param>
/// <param name="encryptKey">加密密钥,要求为16位</param>
/// <returns>加密成功返回加密后的字符串,失败返回源串</returns>

public static string EncryptDES(this string encryptString, string encryptKey)
{
try
{
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 16));
byte[] rgbIV = Keys;
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);

using (var DCSP = Aes.Create())
{
using (MemoryStream mStream = new MemoryStream())
{
using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
{
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray()).Replace('+', '_').Replace('/', '~');
}
}
}
}
catch (Exception ex)
{
throw new Exception("密码加密异常" + ex.Message);
}

}

/// <summary>
/// DES解密字符串
/// </summary>
/// <param name="decryptString">待解密的字符串</param>
/// <param name="decryptKey">解密密钥,要求为16位,和加密密钥相同</param>
/// <returns>解密成功返回解密后的字符串,失败返源串</returns>

public static string DecryptDES(this string decryptString, string decryptKey)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 16));
byte[] rgbIV = Keys;
byte[] inputByteArray = Convert.FromBase64String(decryptString.Replace('_', '+').Replace('~', '/'));
using (var DCSP = Aes.Create())
{
using (MemoryStream mStream = new MemoryStream())
{
using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
{
byte[] inputByteArrays = new byte[inputByteArray.Length];
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Encoding.UTF8.GetString(mStream.ToArray());
}
}
}

}
public static bool TryDecryptDES(this string decryptString, string decryptKey, out string result)
{
result = "";
try
{
result = DecryptDES(decryptString, decryptKey);
return true;
}
catch
{
return false;
}
}
}


3.2 Autofac相关服务类

3.2.1 UserContext

UserContext主要作用就是记录用户信息

public class UserContext
{
/// <summary>
/// 为了尽量减少redis或Memory读取,保证执行效率,将UserContext注入到DI,
/// 每个UserContext的属性至多读取一次redis或Memory缓存从而提高查询效率
/// </summary>
public static UserContext Current
{
get
{
return Context.RequestServices.GetService(typeof(UserContext)) as UserContext;
}
}

private static Microsoft.AspNetCore.Http.HttpContext Context
{
get
{
return Utilities.HttpContext.Current;
}
}
private static ICacheService CacheService
{
get { return GetService<ICacheService>(); }
}

private static T GetService<T>() where T : class
{
return AutofacContainerModule.GetService<T>();
}

public UserInfo UserInfo
{
get
{
if (_userInfo != null)
{
return _userInfo;
}
return GetUserInfo(UserId);
}
}

private UserInfo _userInfo { get; set; }

/// <summary>
/// 角色ID为1的默认为超级管理员
/// </summary>
public bool IsSuperAdmin
{
get { return IsRoleIdSuperAdmin(this.RoleId); }
}
/// <summary>
/// 角色ID为1的默认为超级管理员
/// </summary>
public static bool IsRoleIdSuperAdmin(int roleId)
{
return roleId == 1;
}

public UserInfo GetUserInfo(int userId)
{
if (_userInfo != null) return _userInfo;
if (userId <= 0)
{
_userInfo = new UserInfo();
return _userInfo;
}
string key = userId.GetUserIdKey();
_userInfo = CacheService.Get<UserInfo>(key);
if (_userInfo != null && _userInfo.User_Id > 0) return _userInfo;

_userInfo = DBServerProvider.DbContext.Set<Sys_User>()
.Where(x => x.User_Id == userId).Select(s => new UserInfo()
{
User_Id = userId,
Role_Id = s.Role_Id.GetInt(),
RoleName = s.RoleName,
//2022.08.15增加部门id
DeptId = s.Dept_Id??0,
Token = s.Token,
UserName = s.UserName,
UserTrueName = s.UserTrueName,
Enable = s.Enable
}).FirstOrDefault();

if (_userInfo != null && _userInfo.User_Id > 0)
{
CacheService.AddObject(key, _userInfo);
}
return _userInfo ?? new UserInfo();
}

/// <summary>
/// 获取角色权限时通过安全字典锁定的角色id
/// </summary>
private static ConcurrentDictionary<string, object> objKeyValue = new ConcurrentDictionary<string, object>();

/// <summary>
/// 角色权限的版本号
/// </summary>
private static readonly Dictionary<int, string> rolePermissionsVersion = new Dictionary<int, string>();

/// <summary>
/// 每个角色ID对应的菜单权限(已做静态化处理)
/// 每次获取权限时用当前服务器的版本号与redis/memory缓存的版本比较,如果不同会重新刷新缓存
/// </summary>
private static readonly Dictionary<int, List<Permissions>> rolePermissions = new Dictionary<int, List<Permissions>>();



/// <summary>
/// 获取用户所有的菜单权限
/// </summary>

public List<Permissions> Permissions
{
get
{
return GetPermissions(RoleId);
}
}

/// <summary>
/// 菜单按钮变更时,同时刷新权限缓存2022.05.23
/// </summary>
/// <param name="menuId"></param>
public void RefreshWithMenuActionChange(int menuId)
{
foreach (var roleId in rolePermissions.Where(c => c.Value.Any(x => x.Menu_Id == menuId)).Select(s => s.Key))
{
if (rolePermissionsVersion.ContainsKey(roleId))
{
CacheService.Add(roleId.GetRoleIdKey(), DateTime.Now.ToString("yyyyMMddHHMMssfff"));
}
}

}

/// <summary>
/// 获取单个表的权限
/// </summary>
/// <param name="tableName"></param>
/// <returns></returns>
public Permissions GetPermissions(string tableName)
{
return GetPermissions(RoleId).Where(x => x.TableName == tableName).FirstOrDefault();
}
/// <summary>
/// 2022.03.26
/// 菜单类型1:移动端,0:PC端
/// </summary>
public static int MenuType
{
get
{
return Context.Request.Headers.ContainsKey("uapp") ? 1 : 0;
}
}
/// <summary>
/// 自定条件查询权限
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
public Permissions GetPermissions(Func<Permissions, bool> func)
{
// 2022.03.26增移动端加菜单类型判断
return GetPermissions(RoleId).Where(func).Where(x => x.MenuType == MenuType).FirstOrDefault();
}

private List<Permissions> ActionToArray(List<Permissions> permissions)
{
permissions.ForEach(x =>
{
try
{
var menuAuthArr = x.MenuAuth.DeserializeObject<List<Sys_Actions>>();
x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth)
? new string[0]
: x.UserAuth.Split(",").Where(c => menuAuthArr.Any(m => m.Value == c)).ToArray();

}
catch { }
finally
{
if (x.UserAuthArr == null)
{
x.UserAuthArr = new string[0];
}
}
});
return permissions;
}
private List<Permissions> MenuActionToArray(List<Permissions> permissions)
{
permissions.ForEach(x =>
{
try
{
x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth)
? new string[0]
: x.UserAuth.DeserializeObject<List<Sys_Actions>>().Select(s => s.Value).ToArray();
}
catch { }
finally
{
if (x.UserAuthArr == null)
{
x.UserAuthArr = new string[0];
}
}
});
return permissions;
}
public List<Permissions> GetPermissions(int roleId)
{
if (IsRoleIdSuperAdmin(roleId))
{
//2020.12.27增加菜单界面上不显示,但可以分配权限
var permissions = DBServerProvider.DbContext.Set<Sys_Menu>()
.Where(x => x.Enable == 1 || x.Enable == 2)
.Select(a => new Permissions
{
Menu_Id = a.Menu_Id,
ParentId = a.ParentId,
//2020.05.06增加默认将表名转换成小写,权限验证时不再转换
TableName = (a.TableName ?? "").ToLower(),
//MenuAuth = a.Auth,
UserAuth = a.Auth,
// 2022.03.26增移动端加菜单类型
MenuType = a.MenuType ?? 0
}).ToList();
return MenuActionToArray(permissions);
}
ICacheService cacheService = CacheService;
string roleKey = roleId.GetRoleIdKey();

//角色有缓存,并且当前服务器的角色版本号与redis/memory缓存角色的版本号相同直接返回静态对象角色权限
string currnetVeriosn = "";
if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn)
&& currnetVeriosn == cacheService.Get(roleKey))
{
return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List<Permissions>();
}

//锁定每个角色,通过安全字典减少锁粒度,否则多个同时角色获取缓存会导致阻塞
object objId = objKeyValue.GetOrAdd(roleId.ToString(), new object());
//锁定每个角色
lock (objId)
{
if (rolePermissionsVersion.TryGetValue(roleId, out currnetVeriosn)
&& currnetVeriosn == cacheService.Get(roleKey))
{
return rolePermissions.ContainsKey(roleId) ? rolePermissions[roleId] : new List<Permissions>();
}

//没有redis/memory缓存角色的版本号或与当前服务器的角色版本号不同时,刷新缓存
var dbContext = DBServerProvider.DbContext;
List<Permissions> _permissions = (from a in dbContext.Set<Sys_Menu>()
join b in dbContext.Set<Sys_RoleAuth>()
on a.Menu_Id equals b.Menu_Id
where b.Role_Id == roleId //&& a.ParentId > 0
&& b.AuthValue != ""
orderby a.ParentId
select new Permissions
{
Menu_Id = a.Menu_Id,
ParentId = a.ParentId,
//2020.05.06增加默认将表名转换成小写,权限验证时不再转换
TableName = (a.TableName ?? "").ToLower(),
MenuAuth = a.Auth,
UserAuth = b.AuthValue ?? "",
// 2022.03.26增移动端加菜单类型
MenuType = a.MenuType ?? 0
}).ToList();
ActionToArray(_permissions);
string _version = cacheService.Get(roleKey);
//生成一个唯一版本号标识
if (_version == null)
{
_version = DateTime.Now.ToString("yyyyMMddHHMMssfff");
//将版本号写入缓存
cacheService.Add(roleKey, _version);
}
//刷新当前服务器角色的权限
rolePermissions[roleId] = _permissions;

//写入当前服务器的角色最新版本号
rolePermissionsVersion[roleId] = _version;
return _permissions;
}

}

/// <summary>
/// 判断是否有权限
/// </summary>
/// <param name="tableName"></param>
/// <param name="authName"></param>
/// <param name="roleId"></param>
/// <returns></returns>
public bool ExistsPermissions(string tableName, string authName, int roleId = 0)
{
if (roleId <= 0) roleId = RoleId;
tableName = tableName.ToLower();
return GetPermissions(roleId).Any(x => x.TableName == tableName && x.UserAuthArr.Contains(authName));
}

/// <summary>
/// 判断是否有权限
/// </summary>
/// <param name="tableName"></param>
/// <param name="authName"></param>
/// <param name="roleId"></param>
/// <returns></returns>
public bool ExistsPermissions(string tableName, ActionPermissionOptions actionPermission, int roleId = 0)
{
return ExistsPermissions(tableName, actionPermission.ToString(), roleId);
}
public int UserId
{
get
{
return (Context.User.FindFirstValue(JwtRegisteredClaimNames.Jti)
?? Context.User.FindFirstValue(ClaimTypes.NameIdentifier)).GetInt();
}
}

public string UserName
{
get { return UserInfo.UserName; }
}

public string UserTrueName
{
get { return UserInfo.UserTrueName; }
}

public string Token
{
get { return UserInfo.Token; }
}

public int RoleId
{
get { return UserInfo.Role_Id; }
}

public void LogOut(int userId)
{
CacheService.Remove(userId.GetUserIdKey());
}
}


3.2.2 ActionObserver

ActionObserver记录Action执行的信息

public class ActionObserver
{
//public ActionObserver(IHttpContextAccessor httpContextAccessor)
//{
// this.RequestDate = DateTime.Now;
// this.HttpContext = httpContextAccessor.HttpContext;
//}
/// <summary>
/// 记录action执行的开始时间
/// </summary>
public DateTime RequestDate { get; set; }

/// <summary>
/// 当前请求是否已经写过日志,防止手动与系统自动重复写日志
/// </summary>
public bool IsWrite { get; set; }

public HttpContext HttpContext { get; }
}


3.2.3 ObjectModelValidatorState

ObjectModelValidatorState 对象模型校验服务

public class ObjectModelValidatorState
{
public ObjectModelValidatorState()
{
this.Status = true;
}

public bool Status { get; set; }
public bool HasModelContent { get; set; }
public string Code { get; set; }
public string Message { get; set; }
}
public class ObjectValidatorResult
{
public ObjectValidatorResult()
{

}
public ObjectValidatorResult(bool status)
{
this.Status = status;
}
public ObjectValidatorResult OK(string message)
{
this.Status = true;
this.Message = message;
return this;
}
public ObjectValidatorResult Error(string message)
{
this.Status = false;
this.Message = message;
return this;
}
public bool Status { get; set; }
public string Message { get; set; }
}


其实在Autofac中还注入了数据库服务,下一章讲解。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。