diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj index 1b80529b5..184cf42d8 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj @@ -8,7 +8,7 @@ - + diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs index 0c57ff987..3170b1117 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs @@ -1,16 +1,24 @@ -using Volo.Abp.Collections; - -namespace LINGYUN.Abp.Rules.RulesEngine -{ - public class AbpRulesEngineOptions - { - /// - /// 是否忽略租户 - /// - public bool IgnoreMultiTenancy { get; set; } - - public AbpRulesEngineOptions() - { - } - } -} +using RulesEngine.Models; + +namespace LINGYUN.Abp.Rules.RulesEngine +{ + public class AbpRulesEngineOptions + { + /// + /// 是否忽略租户 + /// + public bool IgnoreMultiTenancy { get; set; } + /// + /// 规则引擎可配置 + /// + public ReSettings Settings { get; set; } + + public AbpRulesEngineOptions() + { + Settings = new ReSettings + { + NestedRuleExecutionMode = NestedRuleExecutionMode.Performance + }; + } + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesResolveContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesResolveContributor.cs index 488d14f36..1702a0425 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesResolveContributor.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesResolveContributor.cs @@ -1,105 +1,104 @@ -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Primitives; -using RulesEngine.Models; -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Volo.Abp.Json; - -namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders -{ - public abstract class FileProviderWorkflowRulesResolveContributor : WorkflowRulesResolveContributorBase - { - protected IMemoryCache RulesCache { get; private set; } - protected IJsonSerializer JsonSerializer { get; private set; } - - protected IFileProvider FileProvider { get; private set; } - - protected FileProviderWorkflowRulesResolveContributor() - { - } - - public override void Initialize(RulesInitializationContext context) - { - Initialize(context.ServiceProvider); - - RulesCache = context.ServiceProvider.GetRequiredService(); - JsonSerializer = context.ServiceProvider.GetRequiredService(); - - FileProvider = BuildFileProvider(context); - } - - protected virtual void Initialize(IServiceProvider serviceProvider) - { - } - - protected abstract IFileProvider BuildFileProvider(RulesInitializationContext context); - - public override async Task ResolveAsync(IWorkflowRulesResolveContext context) - { - if (FileProvider != null) - { - context.WorkflowRules = await GetCachedRulesAsync(context.Type); - } - context.Handled = true; - } - - public override void Shutdown() - { - if (FileProvider != null && FileProvider is IDisposable resource) - { - resource.Dispose(); - } - } - - private async Task GetCachedRulesAsync(Type type, CancellationToken cancellationToken = default) - { - cancellationToken.ThrowIfCancellationRequested(); - - var ruleId = GetRuleId(type); - - return await RulesCache.GetOrCreateAsync(ruleId, - async (entry) => - { - entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(30)); - - return await GetFileSystemRulesAsync(type, cancellationToken); - }); - } - protected abstract int GetRuleId(Type type); - - protected abstract string GetRuleName(Type type); - - protected virtual async Task GetFileSystemRulesAsync(Type type, CancellationToken cancellationToken = default) - { - var ruleId = GetRuleId(type); - var ruleFile = GetRuleName(type); - var fileInfo = FileProvider.GetFileInfo(ruleFile); - if (fileInfo != null && fileInfo.Exists) - { - // 规则文件监控 - // TODO: 删除模块的规则缓存还需要删除RulesEngine中rulesCache已编译的规则缓存 - ChangeToken.OnChange( - () => FileProvider.Watch(ruleFile), - (int ruleId) => - { - RulesCache.Remove(ruleId); - }, ruleId); - - // 打开文本流 - using (var stream = fileInfo.CreateReadStream()) - { - var result = new byte[stream.Length]; - await stream.ReadAsync(result, 0, (int)stream.Length); - var ruleDsl = Encoding.UTF8.GetString(result); - // 解析 - return JsonSerializer.Deserialize(ruleDsl); - } - } - return new WorkflowRules[0]; - } - } -} +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Primitives; +using RulesEngine.Models; +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Json; + +namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders +{ + public abstract class FileProviderWorkflowRulesResolveContributor : WorkflowRulesResolveContributorBase + { + protected IMemoryCache RulesCache { get; private set; } + protected IJsonSerializer JsonSerializer { get; private set; } + + protected IFileProvider FileProvider { get; private set; } + protected FileProviderWorkflowRulesResolveContributor() + { + } + + public override void Initialize(RulesInitializationContext context) + { + Initialize(context.ServiceProvider); + + RulesCache = context.GetRequiredService(); + JsonSerializer = context.GetRequiredService(); + + FileProvider = BuildFileProvider(context); + } + + protected virtual void Initialize(IServiceProvider serviceProvider) + { + } + + protected abstract IFileProvider BuildFileProvider(RulesInitializationContext context); + + public override async Task ResolveAsync(IWorkflowRulesResolveContext context) + { + if (FileProvider != null) + { + context.WorkflowRules = await GetCachedRulesAsync(context.Type); + } + context.Handled = true; + } + + public override void Shutdown() + { + if (FileProvider != null && FileProvider is IDisposable resource) + { + resource.Dispose(); + } + } + + private async Task GetCachedRulesAsync(Type type, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var ruleId = GetRuleId(type); + + return await RulesCache.GetOrCreateAsync(ruleId, + async (entry) => + { + entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(30)); + + return await GetFileSystemRulesAsync(type, cancellationToken); + }); + } + protected abstract int GetRuleId(Type type); + + protected abstract string GetRuleName(Type type); + + protected virtual async Task GetFileSystemRulesAsync(Type type, CancellationToken cancellationToken = default) + { + var ruleId = GetRuleId(type); + var ruleFile = GetRuleName(type); + var fileInfo = FileProvider.GetFileInfo(ruleFile); + if (fileInfo != null && fileInfo.Exists) + { + // 规则文件监控 + ChangeToken.OnChange( + () => FileProvider.Watch(ruleFile), + (int ruleId) => + { + // 清除规则缓存 + RulesCache.Remove(ruleId); + }, ruleId); + + // 打开文本流 + using (var stream = fileInfo.CreateReadStream()) + { + var result = new byte[stream.Length]; + await stream.ReadAsync(result, 0, (int)stream.Length); + var ruleDsl = Encoding.UTF8.GetString(result); + // 解析 + return JsonSerializer.Deserialize(ruleDsl); + } + } + return new WorkflowRules[0]; + } + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePthsicalFileResolveOptions.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePhysicalFileResolveOptions.cs similarity index 75% rename from aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePthsicalFileResolveOptions.cs rename to aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePhysicalFileResolveOptions.cs index 9e87a88ab..4f130a9e8 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePthsicalFileResolveOptions.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/AbpRulesEnginePhysicalFileResolveOptions.cs @@ -1,10 +1,10 @@ -namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical -{ - public class AbpRulesEnginePthsicalFileResolveOptions - { - /// - /// 本地文件路径 - /// - public string PhysicalPath { get; set; } - } -} +namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical +{ + public class AbpRulesEnginePhysicalFileResolveOptions + { + /// + /// 本地文件路径 + /// + public string PhysicalPath { get; set; } + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesResolveContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesResolveContributor.cs index b63ad2d86..b58a80dc3 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesResolveContributor.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesResolveContributor.cs @@ -1,44 +1,44 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Options; -using System; -using System.IO; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical -{ - public class PhysicalFileWorkflowRulesResolveContributor : FileProviderWorkflowRulesResolveContributor, ISingletonDependency - { - public override string Name => "PhysicalFile"; - - private RuleIdGenerator _ruleIdGenerator; - private AbpRulesEngineOptions _rulesEngineOptions; - private AbpRulesEnginePthsicalFileResolveOptions _fileResolveOptions; - - public PhysicalFileWorkflowRulesResolveContributor() - { - } - - protected override void Initialize(IServiceProvider serviceProvider) - { - _ruleIdGenerator = serviceProvider.GetRequiredService(); - _rulesEngineOptions = serviceProvider.GetRequiredService>().Value; - _fileResolveOptions = serviceProvider.GetRequiredService>().Value; - } - - protected override IFileProvider BuildFileProvider(RulesInitializationContext context) - { - // 未指定路径不启用 - if (!_fileResolveOptions.PhysicalPath.IsNullOrWhiteSpace() && - Directory.Exists(_fileResolveOptions.PhysicalPath)) - { - return new PhysicalFileProvider(_fileResolveOptions.PhysicalPath); - } - return null; - } - - protected override int GetRuleId(Type type) => _ruleIdGenerator.CreateRuleId(type, _rulesEngineOptions.IgnoreMultiTenancy); - - protected override string GetRuleName(Type type) => $"{_ruleIdGenerator.CreateRuleName(type, _rulesEngineOptions.IgnoreMultiTenancy)}.json"; - } -} +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Options; +using System; +using System.IO; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical +{ + public class PhysicalFileWorkflowRulesResolveContributor : FileProviderWorkflowRulesResolveContributor, ISingletonDependency + { + public override string Name => "PhysicalFile"; + + private RuleIdGenerator _ruleIdGenerator; + private AbpRulesEngineOptions _rulesEngineOptions; + private AbpRulesEnginePhysicalFileResolveOptions _fileResolveOptions; + + public PhysicalFileWorkflowRulesResolveContributor() + { + } + + protected override void Initialize(IServiceProvider serviceProvider) + { + _ruleIdGenerator = serviceProvider.GetRequiredService(); + _rulesEngineOptions = serviceProvider.GetRequiredService>().Value; + _fileResolveOptions = serviceProvider.GetRequiredService>().Value; + } + + protected override IFileProvider BuildFileProvider(RulesInitializationContext context) + { + // 未指定路径不启用 + if (!_fileResolveOptions.PhysicalPath.IsNullOrWhiteSpace() && + Directory.Exists(_fileResolveOptions.PhysicalPath)) + { + return new PhysicalFileProvider(_fileResolveOptions.PhysicalPath); + } + return null; + } + + protected override int GetRuleId(Type type) => _ruleIdGenerator.CreateRuleId(type, _rulesEngineOptions.IgnoreMultiTenancy); + + protected override string GetRuleName(Type type) => $"{_ruleIdGenerator.CreateRuleName(type, _rulesEngineOptions.IgnoreMultiTenancy)}.json"; + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs index 1c8aaa997..f975e5794 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs @@ -1,82 +1,81 @@ -using RulesEngine; -using RulesEngine.Interfaces; -using RulesEngine.Models; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Engine = RulesEngine.RulesEngine; - -namespace LINGYUN.Abp.Rules.RulesEngine -{ - public class RulesEngineContributor : RuleContributorBase, ISingletonDependency - { - private IRulesEngine _ruleEngine; - private readonly IWorkflowRulesResolver _workflowRulesResolver; - - public RulesEngineContributor( - IWorkflowRulesResolver workflowRulesResolver) - { - _workflowRulesResolver = workflowRulesResolver; - } - - public override void Initialize(RulesInitializationContext context) - { - _ruleEngine = CreateRulesEngine(); - - _workflowRulesResolver.Initialize(context); - } - - public override async Task ExecuteAsync(T input, object[] @params = null, CancellationToken cancellationToken = default) - { - var result = await _workflowRulesResolver.ResolveWorkflowRulesAsync(typeof(T)); - - if (result.WorkflowRules.Any()) - { - await ExecuteRulesAsync(input, result.WorkflowRules.ToArray(), @params); - } - } - - public override void Shutdown() - { - } - /// - /// 重写自行构建规则引擎 - /// - /// - protected virtual Engine CreateRulesEngine() - { - var reSetting = new ReSettings - { - NestedRuleExecutionMode = NestedRuleExecutionMode.Performance - }; - - return new Engine(Logger, reSetting); - } - - protected virtual async Task ExecuteRulesAsync(T input, WorkflowRules[] workflowRules, object[] @params = null) - { - _ruleEngine.AddWorkflow(workflowRules); - - // 传入参与验证的实体参数 - var inputs = new List() - { - input - }; - if (@params != null && @params.Any()) - { - inputs.AddRange(@params); - } - // 其他参数以此类推 - - foreach (var workflowRule in workflowRules) - { - // 执行当前的规则 - var ruleResult = await _ruleEngine.ExecuteAllRulesAsync(workflowRule.WorkflowName, inputs.ToArray()); - // 用户自定义扩展方法,规则校验错误抛出异常 - ruleResult.ThrowOfFaildExecute(); - } - } - } -} +using Microsoft.Extensions.Options; +using RulesEngine; +using RulesEngine.Interfaces; +using RulesEngine.Models; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Engine = RulesEngine.RulesEngine; + +namespace LINGYUN.Abp.Rules.RulesEngine +{ + public class RulesEngineContributor : RuleContributorBase, ISingletonDependency + { + private IRulesEngine _ruleEngine; + private readonly AbpRulesEngineOptions _options; + private readonly IWorkflowRulesResolver _workflowRulesResolver; + + public RulesEngineContributor( + IWorkflowRulesResolver workflowRulesResolver, + IOptions options) + { + _options = options.Value; + _workflowRulesResolver = workflowRulesResolver; + } + + public override void Initialize(RulesInitializationContext context) + { + _ruleEngine = CreateRulesEngine(); + _workflowRulesResolver.Initialize(context); + } + + public override async Task ExecuteAsync(T input, object[] @params = null, CancellationToken cancellationToken = default) + { + var result = await _workflowRulesResolver.ResolveWorkflowRulesAsync(typeof(T)); + + if (result.WorkflowRules.Any()) + { + await ExecuteRulesAsync(input, result.WorkflowRules.ToArray(), @params); + } + } + + public override void Shutdown() + { + } + /// + /// 重写自行构建规则引擎 + /// + /// + protected virtual Engine CreateRulesEngine() + { + return new Engine(Logger, _options.Settings); + } + + protected virtual async Task ExecuteRulesAsync(T input, WorkflowRules[] workflowRules, object[] @params = null) + { + // TODO: 性能缺陷 规则文件每一次调用都会重复编译 + _ruleEngine.AddOrUpdateWorkflow(workflowRules); + + // 传入参与验证的实体参数 + var inputs = new List() + { + input + }; + if (@params != null && @params.Any()) + { + inputs.AddRange(@params); + } + // 其他参数以此类推 + + foreach (var workflowRule in workflowRules) + { + // 执行当前的规则 + var ruleResult = await _ruleEngine.ExecuteAllRulesAsync(workflowRule.WorkflowName, inputs.ToArray()); + // 用户自定义扩展方法,规则校验错误抛出异常 + ruleResult.ThrowOfFaildExecute(); + } + } + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/README.md b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/README.md index fcfc5862a..331596e2d 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/README.md +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/README.md @@ -1,54 +1,54 @@ -# LINGYUN.Abp.Rules.RulesEngine - -## 模块说明 - -集成微软规则引擎的实现 - -默认实现一个本地文件系统规则提供者,根据用户配置的 **AbpRulesEnginePthsicalFileResolveOptions.PhysicalPath** 路径检索规则文件 - -文件名如下: - -PhysicalPath/CurrentTenant.Id[如果存在]/验证规则实体类型名称[typeof(Input).Name].json - -自定义的规则提供者需要实现 **IWorkflowRulesResolveContributor** 接口,可能不需要实现初始化与释放资源,因此提供了一个抽象的 **WorkflowRulesResolveContributorBase** - -并添加到 **AbpRulesEngineResolveOptions.WorkflowRulesResolvers** 中 - -### 基础模块 - -### 高阶模块 - -### 权限定义 - -### 功能定义 - -### 配置定义 - -### 如何使用 - - -```csharp - - [DependsOn( - typeof(AbpRulesEngineModule))] - public class YouProjectModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - // 添加自行实现的规则解析提供者 - options.WorkflowRulesResolvers.Add(new FakeWorkflowRulesResolveContributor()); - }); - - Configure(options => - { - // 指定真实存在的本地文件路径, 否则将不会检索本地规则文件 - options.PhysicalPath = Path.Combine(Directory.GetCurrentDirectory(), "Rules"); - }); - } - } - -``` - -### 更新日志 +# LINGYUN.Abp.Rules.RulesEngine + +## 模块说明 + +集成微软规则引擎的实现 + +默认实现一个本地文件系统规则提供者,根据用户配置的 **AbpRulesEnginePthsicalFileResolveOptions.PhysicalPath** 路径检索规则文件 + +文件名如下: + +PhysicalPath/CurrentTenant.Id[如果存在]/验证规则实体类型名称[typeof(Input).Name].json + +自定义的规则提供者需要实现 **IWorkflowRulesResolveContributor** 接口,可能不需要实现初始化与释放资源,因此提供了一个抽象的 **WorkflowRulesResolveContributorBase** + +并添加到 **AbpRulesEngineResolveOptions.WorkflowRulesResolvers** 中 + +### 基础模块 + +### 高阶模块 + +### 权限定义 + +### 功能定义 + +### 配置定义 + +### 如何使用 + + +```csharp + + [DependsOn( + typeof(AbpRulesEngineModule))] + public class YouProjectModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + // 添加自行实现的规则解析提供者 + options.WorkflowRulesResolvers.Add(new FakeWorkflowRulesResolveContributor()); + }); + + Configure(options => + { + // 指定真实存在的本地文件路径, 否则将不会检索本地规则文件 + options.PhysicalPath = Path.Combine(Directory.GetCurrentDirectory(), "Rules"); + }); + } + } + +``` + +### 更新日志 diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RulesInitializationContext.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RulesInitializationContext.cs index bc2dd08b6..fe5779821 100644 --- a/aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RulesInitializationContext.cs +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RulesInitializationContext.cs @@ -1,16 +1,20 @@ -using System; - -namespace LINGYUN.Abp.Rules -{ - public class RulesInitializationContext : IServiceProvider - { - public IServiceProvider ServiceProvider { get; } - - internal RulesInitializationContext(IServiceProvider serviceProvider) - { - ServiceProvider = serviceProvider; - } - - public object GetService(Type serviceType) => ServiceProvider.GetService(serviceType); - } -} +using System; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.Rules +{ + public class RulesInitializationContext : IServiceProvider, IHasExtraProperties + { + public IServiceProvider ServiceProvider { get; } + + public ExtraPropertyDictionary ExtraProperties { get; } + + internal RulesInitializationContext(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + ExtraProperties = new ExtraPropertyDictionary(); + } + + public object GetService(Type serviceType) => ServiceProvider.GetService(serviceType); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestModule.cs index 1e9372363..970cff99b 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestModule.cs @@ -1,21 +1,21 @@ -using LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical; -using LINGYUN.Abp.Tests; -using System.IO; -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.Rules.RulesEngine -{ - [DependsOn( - typeof(AbpRulesEngineModule), - typeof(AbpTestsBaseModule))] - public class AbpRulesEngineTestModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.PhysicalPath = Path.Combine(Directory.GetCurrentDirectory(), "Rules"); - }); - } - } -} +using LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical; +using LINGYUN.Abp.Tests; +using System.IO; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Rules.RulesEngine +{ + [DependsOn( + typeof(AbpRulesEngineModule), + typeof(AbpTestsBaseModule))] + public class AbpRulesEngineTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.PhysicalPath = Path.Combine(Directory.GetCurrentDirectory(), "Rules"); + }); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInputRuleTests.cs b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInputRuleTests.cs index 46d60ed2c..ac0a148e2 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInputRuleTests.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInputRuleTests.cs @@ -1,117 +1,118 @@ -using Shouldly; -using System.Threading.Tasks; -using Volo.Abp.Validation; -using Xunit; - -namespace LINGYUN.Abp.Rules.RulesEngine -{ - public class TestInputRuleTests : AbpRulesEngineTestBase - { - private readonly IRuleProvider _ruleProvider; - - public TestInputRuleTests() - { - _ruleProvider = GetRequiredService(); - } - - [Fact] - public async Task Input_Required_Should_Required() - { - var input = new TestInput - { - Integer1 = 101, - Integer2 = 99, - Length = "123456" - } - ; - var exception = await Assert.ThrowsAsync(async () => - { - await _ruleProvider.ExecuteAsync(input); - }); - - exception.Message.ShouldBe("一个或多个规则未通过"); - exception.ValidationErrors.Count.ShouldBe(1); - exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Required 必须输入!"); - } - - [Fact] - public async Task Input_Integer1_Should_MustBeGreaterThan100() - { - var input = new TestInput - { - Required = "123456", - Integer1 = 99, - Integer2 = 99, - Length = "123456" - }; - var exception = await Assert.ThrowsAsync(async () => - { - await _ruleProvider.ExecuteAsync(input); - }); - - exception.Message.ShouldBe("一个或多个规则未通过"); - exception.ValidationErrors.Count.ShouldBe(1); - exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer1 必须大于100!"); - } - - [Fact] - public async Task Input_Integer2_Should_MustBeLessThan100() - { - var input = new TestInput - { - Required = "123456", - Integer1 = 101, - Integer2 = 100, - Length = "123456" - }; - var exception = await Assert.ThrowsAsync(async () => - { - await _ruleProvider.ExecuteAsync(input); - }); - - exception.Message.ShouldBe("一个或多个规则未通过"); - exception.ValidationErrors.Count.ShouldBe(1); - exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer2 必须小于100!"); - } - - [Fact] - public async Task Input_Sum_Integer1_And_Integer2_Should_MustBeGreaterThan150() - { - var input = new TestInput - { - Required = "1", - Integer1 = 101, - Integer2 = 48, - Length = "123456" - }; - var exception = await Assert.ThrowsAsync(async () => - { - await _ruleProvider.ExecuteAsync(input); - }); - - exception.Message.ShouldBe("一个或多个规则未通过"); - exception.ValidationErrors.Count.ShouldBe(1); - exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer1 与 Integer2 之和 必须大于150!"); - } - - [Fact] - public async Task Input_Required_Length_Should_MustBeGreaterThan5() - { - var input = new TestInput - { - Required = "1", - Integer1 = 101, - Integer2 = 50, - Length = "12345" - }; - var exception = await Assert.ThrowsAsync(async () => - { - await _ruleProvider.ExecuteAsync(input); - }); - - exception.Message.ShouldBe("一个或多个规则未通过"); - exception.ValidationErrors.Count.ShouldBe(1); - exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Length 长度必须大于5!"); - } - } -} +using Shouldly; +using System; +using System.Threading.Tasks; +using Volo.Abp.Validation; +using Xunit; + +namespace LINGYUN.Abp.Rules.RulesEngine +{ + public class TestInputRuleTests : AbpRulesEngineTestBase + { + private readonly IRuleProvider _ruleProvider; + + public TestInputRuleTests() + { + _ruleProvider = GetRequiredService(); + } + + [Fact] + public async Task Input_Required_Should_Required() + { + var input = new TestInput + { + Integer1 = 101, + Integer2 = 99, + Length = "123456" + } + ; + var exception = await Assert.ThrowsAsync(async () => + { + await _ruleProvider.ExecuteAsync(input); + }); + + exception.Message.ShouldBe("一个或多个规则未通过"); + exception.ValidationErrors.Count.ShouldBe(1); + exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Required 必须输入!"); + } + + [Fact] + public async Task Input_Integer1_Should_MustBeGreaterThan100() + { + var input = new TestInput + { + Required = "123456", + Integer1 = 99, + Integer2 = 99, + Length = "123456" + }; + var exception = await Assert.ThrowsAsync(async () => + { + await _ruleProvider.ExecuteAsync(input); + }); + + exception.Message.ShouldBe("一个或多个规则未通过"); + exception.ValidationErrors.Count.ShouldBe(1); + exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer1 必须大于100!"); + } + + [Fact] + public async Task Input_Integer2_Should_MustBeLessThan100() + { + var input = new TestInput + { + Required = "123456", + Integer1 = 101, + Integer2 = 100, + Length = "123456" + }; + var exception = await Assert.ThrowsAsync(async () => + { + await _ruleProvider.ExecuteAsync(input); + }); + + exception.Message.ShouldBe("一个或多个规则未通过"); + exception.ValidationErrors.Count.ShouldBe(1); + exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer2 必须小于100!"); + } + + [Fact] + public async Task Input_Sum_Integer1_And_Integer2_Should_MustBeGreaterThan150() + { + var input = new TestInput + { + Required = "1", + Integer1 = 101, + Integer2 = 48, + Length = "123456" + }; + var exception = await Assert.ThrowsAsync(async () => + { + await _ruleProvider.ExecuteAsync(input); + }); + + exception.Message.ShouldBe("一个或多个规则未通过"); + exception.ValidationErrors.Count.ShouldBe(1); + exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Integer1 与 Integer2 之和 必须大于150!"); + } + + [Fact] + public async Task Input_Required_Length_Should_MustBeGreaterThan5() + { + var input = new TestInput + { + Required = "1", + Integer1 = 101, + Integer2 = 50, + Length = "12345" + }; + var exception = await Assert.ThrowsAsync(async () => + { + await _ruleProvider.ExecuteAsync(input); + }); + + exception.Message.ShouldBe("一个或多个规则未通过"); + exception.ValidationErrors.Count.ShouldBe(1); + exception.ValidationErrors[0].ErrorMessage.ShouldBe("字段 Length 长度必须大于5!"); + } + } +}