From cc1ee93c8873c726a9c93254da8b3dccd5dc3cf5 Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Mon, 10 May 2021 22:17:31 +0800
Subject: [PATCH] add rules sopport
---
aspnet-core/LINGYUN.MicroService.Common.sln | 31 ++++
.../Properties/launchSettings.json | 27 +++
...UN.Abp.OssManagement.HttpApi.Client.csproj | 18 ++
.../AbpOssManagementHttpApiClientModule.cs | 20 +++
.../LINGYUNApiDescriptionFinder.cs | 162 ++++++++++++++++++
.../LINGYUN.Abp.Rules.NRules.csproj | 18 ++
.../Abp/Rules/NRules/AbpNRulesModule.cs | 22 +++
.../Rules/NRules/DefaultActionInterceptor.cs | 14 ++
.../Rules/NRules/DefaultDependencyResolver.cs | 21 +++
.../Abp/Rules/NRules/NRulesContributor.cs | 39 +++++
.../LINGYUN.Abp.Rules.RulesEngine.csproj | 19 ++
.../Rules/RulesEngine/AbpRulesEngineModule.cs | 30 ++++
.../RulesEngine/AbpRulesEngineOptions.cs | 25 +++
.../FileProviderWorkflowRulesContributor.cs | 99 +++++++++++
.../PhysicalFileWorkflowRulesContributor.cs | 42 +++++
.../RulesEngine/IWorkflowRulesContributor.cs | 15 ++
.../NullWorkflowRulesContributor.cs | 25 +++
.../RulesEngine/RulesEngineContributor.cs | 94 ++++++++++
.../LINGYUN.Abp.Rules.RulesEngine/README.md | 44 +++++
.../ListofRuleResultTreeExtension.cs | 76 ++++++++
.../LINGYUN.Abp.Rules.csproj | 14 ++
.../LINGYUN/Abp/Rules/AbpRulesModule.cs | 26 +++
.../LINGYUN/Abp/Rules/AbpRulesOptions.cs | 14 ++
.../LINGYUN/Abp/Rules/IRuleContributor.cs | 14 ++
.../LINGYUN/Abp/Rules/IRuleProvider.cs | 10 ++
.../LINGYUN/Abp/Rules/RuleContributorBase.cs | 31 ++++
.../LINGYUN/Abp/Rules/RuleIdGenerator.cs | 45 +++++
.../LINGYUN/Abp/Rules/RuleProvider.cs | 65 +++++++
.../Abp/Rules/RulesInitializationContext.cs | 16 ++
.../modules/rules/LINGYUN.Abp.Rules/README.md | 54 ++++++
....OssManagement.HttpApi.Client.Tests.csproj | 27 +++
.../AbpOssManagementHttpApiClientTestBase.cs | 13 ++
...AbpOssManagementHttpApiClientTestModule.cs | 24 +++
.../OssManagement/OssObjectAppServiceTests.cs | 35 ++++
.../StaticFilesAppServiceTests.cs | 35 ++++
...LINGYUN.Abp.Rules.RulesEngine.Tests.csproj | 36 ++++
.../RulesEngine/AbpRulesEngineTestBase.cs | 8 +
.../RulesEngine/AbpRulesEngineTestModule.cs | 23 +++
.../Abp/Rules/RulesEngine/TestInput.cs | 24 +++
.../Rules/RulesEngine/TestInputRuleTests.cs | 117 +++++++++++++
.../RulesEngine/TestMultipleRuleInputTests.cs | 38 ++++
.../Rules/TestInput.json | 42 +++++
.../Rules/TestMultipleRuleInput.json | 58 +++++++
43 files changed, 1610 insertions(+)
create mode 100644 aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.IdentityModel.Web/Properties/launchSettings.json
create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj
create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientModule.cs
create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN.Abp.Rules.NRules.csproj
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesModule.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultActionInterceptor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultDependencyResolver.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/NRulesContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineModule.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/IWorkflowRulesContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/NullWorkflowRulesContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/README.md
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/RulesEngine/ListofRuleResultTreeExtension.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesModule.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesOptions.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleContributor.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleProvider.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleContributorBase.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleIdGenerator.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleProvider.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RulesInitializationContext.cs
create mode 100644 aspnet-core/modules/rules/LINGYUN.Abp.Rules/README.md
create mode 100644 aspnet-core/tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests.csproj
create mode 100644 aspnet-core/tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientTestBase.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientTestModule.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests/LINGYUN/Abp/OssManagement/OssObjectAppServiceTests.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.OssManagement.HttpApi.Client.Tests/LINGYUN/Abp/OssManagement/StaticFilesAppServiceTests.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestBase.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineTestModule.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInput.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestInputRuleTests.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN/Abp/Rules/RulesEngine/TestMultipleRuleInputTests.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/Rules/TestInput.json
create mode 100644 aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/Rules/TestMultipleRuleInput.json
diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln
index e940daeb2..96c4cf875 100644
--- a/aspnet-core/LINGYUN.MicroService.Common.sln
+++ b/aspnet-core/LINGYUN.MicroService.Common.sln
@@ -142,6 +142,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors.Asp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Client", "modules\dapr\LINGYUN.Abp.Dapr.Client\LINGYUN.Abp.Dapr.Client.csproj", "{879791A3-BD69-42E4-A3BC-9878EFAADDD1}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rules", "rules", "{C8891F1A-E6E5-448A-B527-EBFA44D20808}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules", "modules\rules\LINGYUN.Abp.Rules\LINGYUN.Abp.Rules.csproj", "{5133D83C-9B23-491C-8780-3F9BBDBD0351}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.NRules", "modules\rules\LINGYUN.Abp.Rules.NRules\LINGYUN.Abp.Rules.NRules.csproj", "{B8E5026B-188F-422F-A1EA-502C4A394585}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.RulesEngine", "modules\rules\LINGYUN.Abp.Rules.RulesEngine\LINGYUN.Abp.Rules.RulesEngine.csproj", "{E861BE01-689D-4637-A5DC-E78E234F83FB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.RulesEngine.Tests", "tests\LINGYUN.Abp.Rules.RulesEngine.Tests\LINGYUN.Abp.Rules.RulesEngine.Tests.csproj", "{CF253F0A-3A45-40EE-875F-0E57C8968C48}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -368,6 +378,22 @@ Global
{879791A3-BD69-42E4-A3BC-9878EFAADDD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{879791A3-BD69-42E4-A3BC-9878EFAADDD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{879791A3-BD69-42E4-A3BC-9878EFAADDD1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5133D83C-9B23-491C-8780-3F9BBDBD0351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5133D83C-9B23-491C-8780-3F9BBDBD0351}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5133D83C-9B23-491C-8780-3F9BBDBD0351}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5133D83C-9B23-491C-8780-3F9BBDBD0351}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B8E5026B-188F-422F-A1EA-502C4A394585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B8E5026B-188F-422F-A1EA-502C4A394585}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B8E5026B-188F-422F-A1EA-502C4A394585}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B8E5026B-188F-422F-A1EA-502C4A394585}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E861BE01-689D-4637-A5DC-E78E234F83FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E861BE01-689D-4637-A5DC-E78E234F83FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E861BE01-689D-4637-A5DC-E78E234F83FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E861BE01-689D-4637-A5DC-E78E234F83FB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CF253F0A-3A45-40EE-875F-0E57C8968C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF253F0A-3A45-40EE-875F-0E57C8968C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF253F0A-3A45-40EE-875F-0E57C8968C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF253F0A-3A45-40EE-875F-0E57C8968C48}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -439,6 +465,11 @@ Global
{E263A9ED-D5DB-4495-A0C7-6268ED92EB92} = {7FDFB22F-1BFF-4E05-9427-78B7A8461D50}
{E74FF671-6E5E-430C-9211-ED910634DDBE} = {7FDFB22F-1BFF-4E05-9427-78B7A8461D50}
{879791A3-BD69-42E4-A3BC-9878EFAADDD1} = {7FDFB22F-1BFF-4E05-9427-78B7A8461D50}
+ {C8891F1A-E6E5-448A-B527-EBFA44D20808} = {02EA4E78-5891-43BC-944F-3E52FEE032E4}
+ {5133D83C-9B23-491C-8780-3F9BBDBD0351} = {C8891F1A-E6E5-448A-B527-EBFA44D20808}
+ {B8E5026B-188F-422F-A1EA-502C4A394585} = {C8891F1A-E6E5-448A-B527-EBFA44D20808}
+ {E861BE01-689D-4637-A5DC-E78E234F83FB} = {C8891F1A-E6E5-448A-B527-EBFA44D20808}
+ {CF253F0A-3A45-40EE-875F-0E57C8968C48} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8}
diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.IdentityModel.Web/Properties/launchSettings.json b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.IdentityModel.Web/Properties/launchSettings.json
new file mode 100644
index 000000000..ea7755ed2
--- /dev/null
+++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.IdentityModel.Web/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:25348/",
+ "sslPort": 44377
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "LINGYUN.Abp.Dapr.Actors.IdentityModel.Web": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:5001;http://localhost:5000"
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj
new file mode 100644
index 000000000..baddb08b9
--- /dev/null
+++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientModule.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientModule.cs
new file mode 100644
index 000000000..a774a27b5
--- /dev/null
+++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiClientModule.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Http.Client;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.OssManagement
+{
+ [DependsOn(
+ typeof(AbpOssManagementApplicationContractsModule),
+ typeof(AbpHttpClientModule))]
+ public class AbpOssManagementHttpApiClientModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddHttpClientProxies(
+ typeof(AbpOssManagementApplicationContractsModule).Assembly,
+ OssManagementRemoteServiceConsts.RemoteServiceName
+ );
+ }
+ }
+}
diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs
new file mode 100644
index 000000000..2fe15b2c0
--- /dev/null
+++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs
@@ -0,0 +1,162 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Reflection;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Http.Client.DynamicProxying;
+using Volo.Abp.Http.Modeling;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Threading;
+using Volo.Abp.Tracing;
+
+namespace LINGYUN.Abp.OssManagement
+{
+ public class LINGYUNApiDescriptionFinder : IApiDescriptionFinder, ITransientDependency
+ {
+ public ICancellationTokenProvider CancellationTokenProvider { get; set; }
+ protected IApiDescriptionCache Cache { get; }
+ protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; }
+ protected ICorrelationIdProvider CorrelationIdProvider { get; }
+ protected ICurrentTenant CurrentTenant { get; }
+
+ public LINGYUNApiDescriptionFinder(
+ IApiDescriptionCache cache,
+ IOptions abpCorrelationIdOptions,
+ ICorrelationIdProvider correlationIdProvider,
+ ICurrentTenant currentTenant)
+ {
+ Cache = cache;
+ AbpCorrelationIdOptions = abpCorrelationIdOptions.Value;
+ CorrelationIdProvider = correlationIdProvider;
+ CurrentTenant = currentTenant;
+ CancellationTokenProvider = NullCancellationTokenProvider.Instance;
+ }
+
+ public async Task FindActionAsync(HttpClient client, string baseUrl, Type serviceType, MethodInfo method)
+ {
+ var apiDescription = await GetApiDescriptionAsync(client, baseUrl);
+
+ //TODO: Cache finding?
+
+ var methodParameters = method.GetParameters().ToArray();
+
+ foreach (var module in apiDescription.Modules.Values)
+ {
+ foreach (var controller in module.Controllers.Values)
+ {
+ if (!controller.Implements(serviceType))
+ {
+ continue;
+ }
+
+ foreach (var action in controller.Actions.Values)
+ {
+ if (action.Name == method.Name && action.ParametersOnMethod.Count == methodParameters.Length)
+ {
+ var found = true;
+
+ for (int i = 0; i < methodParameters.Length; i++)
+ {
+ if (!TypeMatches(action.ParametersOnMethod[i], methodParameters[i]))
+ {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ return action;
+ }
+ }
+ }
+ }
+ }
+
+ throw new AbpException($"Could not found remote action for method: {method} on the URL: {baseUrl}");
+ }
+
+ public virtual async Task GetApiDescriptionAsync(HttpClient client, string baseUrl)
+ {
+ return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(client, baseUrl));
+ }
+
+ protected virtual async Task GetApiDescriptionFromServerAsync(
+ HttpClient client,
+ string baseUrl)
+ {
+ var requestMessage = new HttpRequestMessage(
+ HttpMethod.Get,
+ baseUrl.EnsureEndsWith('/') + "api/abp/api-definition"
+ );
+
+ AddHeaders(requestMessage);
+
+ var response = await client.SendAsync(
+ requestMessage,
+ CancellationTokenProvider.Token
+ );
+
+ if (!response.IsSuccessStatusCode)
+ {
+ throw new AbpException("Remote service returns error! StatusCode = " + response.StatusCode);
+ }
+
+ var content = await response.Content.ReadAsStringAsync();
+
+ var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
+ });
+
+ return (ApplicationApiDescriptionModel)result;
+ }
+
+ protected virtual void AddHeaders(HttpRequestMessage requestMessage)
+ {
+ //CorrelationId
+ requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
+
+ //TenantId
+ if (CurrentTenant.Id.HasValue)
+ {
+ //TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
+ requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
+ }
+
+ //Culture
+ //TODO: Is that the way we want? Couldn't send the culture (not ui culture)
+ var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
+ if (!currentCulture.IsNullOrEmpty())
+ {
+ requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
+ }
+
+ //X-Requested-With
+ requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest");
+ }
+
+ protected virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter)
+ {
+ return NormalizeTypeName(actionParameter.TypeAsString) ==
+ NormalizeTypeName(methodParameter.ParameterType.GetFullNameWithAssemblyName());
+ }
+
+ protected virtual string NormalizeTypeName(string typeName)
+ {
+ const string placeholder = "%COREFX%";
+ const string netCoreLib = "System.Private.CoreLib";
+ const string netFxLib = "mscorlib";
+
+ return typeName.Replace(netCoreLib, placeholder).Replace(netFxLib, placeholder);
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN.Abp.Rules.NRules.csproj b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN.Abp.Rules.NRules.csproj
new file mode 100644
index 000000000..0712d61cf
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN.Abp.Rules.NRules.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesModule.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesModule.cs
new file mode 100644
index 000000000..482c1ae72
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesModule.cs
@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using NRules.Fluent;
+using NRules.RuleModel;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Rules.NRules
+{
+ [DependsOn(
+ typeof(AbpRulesModule))]
+ public class AbpNRulesModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddSingleton();
+
+ Configure(options =>
+ {
+ options.Contributors.Add();
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultActionInterceptor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultActionInterceptor.cs
new file mode 100644
index 000000000..de9caea68
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultActionInterceptor.cs
@@ -0,0 +1,14 @@
+using NRules.Extensibility;
+using NRules.RuleModel;
+using System.Collections.Generic;
+
+namespace LINGYUN.Abp.Rules.NRules
+{
+ public class DefaultActionInterceptor : IActionInterceptor
+ {
+ public void Intercept(IContext context, IEnumerable actions)
+ {
+
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultDependencyResolver.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultDependencyResolver.cs
new file mode 100644
index 000000000..0faf0be2f
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultDependencyResolver.cs
@@ -0,0 +1,21 @@
+using NRules.Extensibility;
+using System;
+
+namespace LINGYUN.Abp.Rules.NRules
+{
+ public class DefaultDependencyResolver : IDependencyResolver
+ {
+ private readonly IServiceProvider _serviceProvider;
+
+ public DefaultDependencyResolver(
+ IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ public object Resolve(IResolutionContext context, Type serviceType)
+ {
+ return _serviceProvider.GetService(serviceType);
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/NRulesContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/NRulesContributor.cs
new file mode 100644
index 000000000..5e509d057
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/NRulesContributor.cs
@@ -0,0 +1,39 @@
+using Microsoft.Extensions.DependencyInjection;
+using NRules;
+using NRules.RuleModel;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.Rules.NRules
+{
+ public class NRulesContributor : RuleContributorBase, ISingletonDependency
+ {
+ private ISessionFactory _sessionFactory;
+
+ public override void Initialize(RulesInitializationContext context)
+ {
+ var repository = context.GetRequiredService();
+ _sessionFactory = repository.Compile();
+ _sessionFactory.DependencyResolver = new DefaultDependencyResolver(context.ServiceProvider);
+ _sessionFactory.ActionInterceptor = new DefaultActionInterceptor();
+ }
+
+ public override Task ExecuteAsync(T input, object[] @params = null, CancellationToken cancellationToken = default)
+ {
+ var session = _sessionFactory.CreateSession();
+
+ session.Insert(input);
+ if (@params != null && @params.Any())
+ {
+ session.InsertAll(@params);
+ }
+
+ // TODO: 需要研究源码
+ session.Fire(cancellationToken);
+
+ return Task.CompletedTask;
+ }
+ }
+}
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
new file mode 100644
index 000000000..b440bbab5
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN.Abp.Rules.RulesEngine.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineModule.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineModule.cs
new file mode 100644
index 000000000..0487d113d
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineModule.cs
@@ -0,0 +1,30 @@
+using LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Json;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Rules.RulesEngine
+{
+ [DependsOn(
+ typeof(AbpRulesModule),
+ typeof(AbpJsonModule))]
+ public class AbpRulesEngineModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddMemoryCache();
+
+ Configure(options =>
+ {
+ options.Contributors.Add();
+ });
+
+ Configure(options =>
+ {
+ // 加入防止空引用
+ options.Contributors.Add();
+ options.Contributors.Add();
+ });
+ }
+ }
+}
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
new file mode 100644
index 000000000..176358fee
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/AbpRulesEngineOptions.cs
@@ -0,0 +1,25 @@
+using Volo.Abp.Collections;
+
+namespace LINGYUN.Abp.Rules.RulesEngine
+{
+ public class AbpRulesEngineOptions
+ {
+ ///
+ /// 本地文件路径
+ ///
+ public string PhysicalPath { get; set; }
+ ///
+ /// 是否忽略租户
+ ///
+ public bool IgnoreMultiTenancy { get; set; }
+ ///
+ /// 规则提供者类型
+ ///
+ public ITypeList Contributors { get; }
+
+ public AbpRulesEngineOptions()
+ {
+ Contributors = new TypeList();
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesContributor.cs
new file mode 100644
index 000000000..b578c31dd
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/FileProviderWorkflowRulesContributor.cs
@@ -0,0 +1,99 @@
+using Microsoft.Extensions.Caching.Memory;
+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 FileProviderWorkflowRulesContributor : IWorkflowRulesContributor
+ {
+ protected IMemoryCache RulesCache { get; }
+ protected IJsonSerializer JsonSerializer { get; }
+
+ protected IFileProvider FileProvider { get; private set; }
+
+ protected FileProviderWorkflowRulesContributor(
+ IMemoryCache ruleCache,
+ IJsonSerializer jsonSerializer)
+ {
+ RulesCache = ruleCache;
+ JsonSerializer = jsonSerializer;
+ }
+
+ public void Initialize()
+ {
+ FileProvider = BuildFileProvider();
+ }
+
+ protected abstract IFileProvider BuildFileProvider();
+
+ public async Task LoadAsync(CancellationToken cancellationToken = default)
+ {
+ if (FileProvider != null)
+ {
+ return await GetCachedRulesAsync(cancellationToken);
+ }
+ return new WorkflowRules[0];
+ }
+
+ public void Shutdown()
+ {
+ if (FileProvider != null && FileProvider is IDisposable resource)
+ {
+ resource.Dispose();
+ }
+ }
+
+ private async Task GetCachedRulesAsync(CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var ruleId = GetRuleId();
+
+ return await RulesCache.GetOrCreateAsync(ruleId,
+ async (entry) =>
+ {
+ entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(30));
+
+ return await GetFileSystemRulesAsync(cancellationToken);
+ });
+ }
+ protected abstract int GetRuleId();
+
+ protected abstract string GetRuleName();
+
+ protected virtual async Task GetFileSystemRulesAsync(CancellationToken cancellationToken = default)
+ {
+ var ruleId = GetRuleId();
+ var ruleFile = GetRuleName();
+ 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];
+ }
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesContributor.cs
new file mode 100644
index 000000000..1060e2631
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/FileProviders/Physical/PhysicalFileWorkflowRulesContributor.cs
@@ -0,0 +1,42 @@
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Options;
+using System;
+using System.IO;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Json;
+
+namespace LINGYUN.Abp.Rules.RulesEngine.FileProviders.Physical
+{
+ public class PhysicalFileWorkflowRulesContributor : FileProviderWorkflowRulesContributor, ISingletonDependency
+ {
+ private readonly RuleIdGenerator _ruleIdGenerator;
+ private readonly AbpRulesEngineOptions _options;
+ public PhysicalFileWorkflowRulesContributor(
+ IMemoryCache ruleCache,
+ RuleIdGenerator ruleIdGenerator,
+ IJsonSerializer jsonSerializer,
+ IOptions options)
+ : base(ruleCache, jsonSerializer)
+ {
+ _ruleIdGenerator = ruleIdGenerator;
+
+ _options = options.Value;
+ }
+
+ protected override IFileProvider BuildFileProvider()
+ {
+ // 未指定路径不启用
+ if (!_options.PhysicalPath.IsNullOrWhiteSpace() &&
+ Directory.Exists(_options.PhysicalPath))
+ {
+ return new PhysicalFileProvider(_options.PhysicalPath);
+ }
+ return null;
+ }
+
+ protected override int GetRuleId() => _ruleIdGenerator.CreateRuleId(typeof(T), _options.IgnoreMultiTenancy);
+
+ protected override string GetRuleName() => $"{_ruleIdGenerator.CreateRuleName(typeof(T), _options.IgnoreMultiTenancy)}.json";
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/IWorkflowRulesContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/IWorkflowRulesContributor.cs
new file mode 100644
index 000000000..b13da479d
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/IWorkflowRulesContributor.cs
@@ -0,0 +1,15 @@
+using RulesEngine.Models;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.Rules.RulesEngine
+{
+ public interface IWorkflowRulesContributor
+ {
+ void Initialize();
+
+ Task LoadAsync(CancellationToken cancellationToken = default);
+
+ void Shutdown();
+ }
+}
diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/NullWorkflowRulesContributor.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/NullWorkflowRulesContributor.cs
new file mode 100644
index 000000000..c80dca944
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/NullWorkflowRulesContributor.cs
@@ -0,0 +1,25 @@
+using RulesEngine.Models;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.Rules.RulesEngine
+{
+ public class NullWorkflowRulesContributor : IWorkflowRulesContributor, ISingletonDependency
+ {
+ public void Initialize()
+ {
+
+ }
+
+ public Task LoadAsync(CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(new WorkflowRules[0]);
+ }
+
+ public void Shutdown()
+ {
+
+ }
+ }
+}
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
new file mode 100644
index 000000000..8ca8c28f4
--- /dev/null
+++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.RulesEngine/LINGYUN/Abp/Rules/RulesEngine/RulesEngineContributor.cs
@@ -0,0 +1,94 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using RulesEngine;
+using RulesEngine.Interfaces;
+using RulesEngine.Models;
+using System;
+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 IEnumerable _workflowRulesContributors;
+
+ public RulesEngineContributor(
+ IServiceProvider serviceProvider,
+ IOptions options)
+ {
+ _workflowRulesContributors = options.Value
+ .Contributors
+ .Select(serviceProvider.GetRequiredService)
+ .Cast()
+ .ToArray();
+ }
+
+ public override void Initialize(RulesInitializationContext context)
+ {
+ var reSetting = new ReSettings
+ {
+ NestedRuleExecutionMode = NestedRuleExecutionMode.Performance
+ };
+
+ _ruleEngine = new Engine(Logger, reSetting);
+
+ foreach (var contributor in _workflowRulesContributors)
+ {
+ contributor.Initialize();
+ }
+ }
+
+ public override async Task ExecuteAsync(T input, object[] @params = null, CancellationToken cancellationToken = default)
+ {
+ List workflowRules = new();
+
+ foreach (var contributor in _workflowRulesContributors)
+ {
+ workflowRules.AddRange(await contributor.LoadAsync(cancellationToken));
+ }
+
+ if (workflowRules.Any())
+ {
+ await ExecuteRulesAsync(input, workflowRules.ToArray(), @params);
+ }
+ }
+
+ public override void Shutdown()
+ {
+ foreach (var contributor in _workflowRulesContributors)
+ {
+ contributor.Shutdown();
+ }
+ }
+
+ protected virtual async Task ExecuteRulesAsync(T input, WorkflowRules[] workflowRules, object[] @params = null)
+ {
+ _ruleEngine.AddWorkflow(workflowRules);
+
+ // 传入参与验证的实体参数
+ var inputs = new List