diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln index 96c4cf875..13e67fa2f 100644 --- a/aspnet-core/LINGYUN.MicroService.Common.sln +++ b/aspnet-core/LINGYUN.MicroService.Common.sln @@ -152,6 +152,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules.RulesEngi 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 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Rules.NRules.Tests", "tests\LINGYUN.Abp.Rules.NRules.Tests\LINGYUN.Abp.Rules.NRules.Tests.csproj", "{EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -394,6 +396,10 @@ Global {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 + {EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -470,6 +476,7 @@ Global {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} + {EF03A0A7-A93E-4DEF-A33E-F5A82E995FBF} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} 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 index 482c1ae72..5da67aeac 100644 --- 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 @@ -1,6 +1,6 @@ using Microsoft.Extensions.DependencyInjection; -using NRules.Fluent; -using NRules.RuleModel; +using System; +using System.Collections.Generic; using Volo.Abp.Modularity; namespace LINGYUN.Abp.Rules.NRules @@ -9,14 +9,37 @@ namespace LINGYUN.Abp.Rules.NRules typeof(AbpRulesModule))] public class AbpNRulesModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + AddDefinitionRules(context.Services); + } + public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddSingleton(); + context.Services.AddNRules(); Configure(options => { options.Contributors.Add(); }); } + + private static void AddDefinitionRules(IServiceCollection services) + { + var definitionRules = new List(); + + services.OnRegistred(context => + { + if (typeof(RuleBase).IsAssignableFrom(context.ImplementationType)) + { + definitionRules.Add(context.ImplementationType); + } + }); + + services.Configure(options => + { + options.DefinitionRules.AddIfNotContains(definitionRules); + }); + } } } diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesOptions.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesOptions.cs new file mode 100644 index 000000000..9d7fa83c9 --- /dev/null +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/AbpNRulesOptions.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Collections; + +namespace LINGYUN.Abp.Rules.NRules +{ + public class AbpNRulesOptions + { + public ITypeList DefinitionRules { get; } + + public AbpNRulesOptions() + { + DefinitionRules = new TypeList(); + } + } +} 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/ActionInterceptor.cs similarity index 74% rename from aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultActionInterceptor.cs rename to aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/ActionInterceptor.cs index de9caea68..cf7f59cff 100644 --- 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/ActionInterceptor.cs @@ -4,11 +4,11 @@ using System.Collections.Generic; namespace LINGYUN.Abp.Rules.NRules { - public class DefaultActionInterceptor : IActionInterceptor + public class ActionInterceptor : IActionInterceptor { public void Intercept(IContext context, IEnumerable actions) { - + // TODO: Intercept } } } 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/DependencyResolver.cs similarity index 80% rename from aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DefaultDependencyResolver.cs rename to aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/DependencyResolver.cs index 0faf0be2f..945439354 100644 --- 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/DependencyResolver.cs @@ -3,11 +3,11 @@ using System; namespace LINGYUN.Abp.Rules.NRules { - public class DefaultDependencyResolver : IDependencyResolver + public class DependencyResolver : IDependencyResolver { private readonly IServiceProvider _serviceProvider; - public DefaultDependencyResolver( + public DependencyResolver( IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; 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 index 5e509d057..1cdaf7cf1 100644 --- 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 @@ -1,6 +1,8 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using NRules; -using NRules.RuleModel; +using NRules.Fluent; +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -10,28 +12,38 @@ namespace LINGYUN.Abp.Rules.NRules { public class NRulesContributor : RuleContributorBase, ISingletonDependency { - private ISessionFactory _sessionFactory; + private readonly AbpNRulesOptions _options; + private readonly IServiceProvider _serviceProvider; + + public NRulesContributor( + IServiceProvider serviceProvider, + IOptions options) + { + _options = options.Value; + _serviceProvider = serviceProvider; + } public override void Initialize(RulesInitializationContext context) { - var repository = context.GetRequiredService(); - _sessionFactory = repository.Compile(); - _sessionFactory.DependencyResolver = new DefaultDependencyResolver(context.ServiceProvider); - _sessionFactory.ActionInterceptor = new DefaultActionInterceptor(); + context.GetRequiredService() + .Load(loader => loader.From(_options.DefinitionRules)); } public override Task ExecuteAsync(T input, object[] @params = null, CancellationToken cancellationToken = default) { - var session = _sessionFactory.CreateSession(); - - session.Insert(input); - if (@params != null && @params.Any()) + using (var scope = _serviceProvider.CreateScope()) { - session.InsertAll(@params); - } + var session = scope.ServiceProvider.GetRequiredService(); + + session.Insert(input); + if (@params != null && @params.Any()) + { + session.InsertAll(@params); + } - // TODO: 需要研究源码 - session.Fire(cancellationToken); + // TODO: 需要研究源码 + session.Fire(cancellationToken); + } return Task.CompletedTask; } diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleActivator.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleActivator.cs new file mode 100644 index 000000000..5ebe51fcd --- /dev/null +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleActivator.cs @@ -0,0 +1,35 @@ +using NRules.Fluent; +using NRules.Fluent.Dsl; +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Rules.NRules +{ + public class RuleActivator : IRuleActivator + { + private readonly IServiceProvider _serviceProvider; + + public RuleActivator(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public IEnumerable Activate(Type type) + { + var collectionType = typeof(IEnumerable<>).MakeGenericType(type); + var rules = _serviceProvider.GetService(collectionType); + + if (rules != null) + { + return (IEnumerable)rules; + } + + return ActivateDefault(type); + } + + private static IEnumerable ActivateDefault(Type type) + { + yield return (Rule)Activator.CreateInstance(type); + } + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleBase.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleBase.cs new file mode 100644 index 000000000..e43edf665 --- /dev/null +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/LINGYUN/Abp/Rules/NRules/RuleBase.cs @@ -0,0 +1,9 @@ +using NRules.Fluent.Dsl; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Rules.NRules +{ + public abstract class RuleBase : Rule, ITransientDependency + { + } +} diff --git a/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/Microsoft/Extensions/DependencyInjection/NRulesServiceCollectionExtensions.cs b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/Microsoft/Extensions/DependencyInjection/NRulesServiceCollectionExtensions.cs new file mode 100644 index 000000000..33c364098 --- /dev/null +++ b/aspnet-core/modules/rules/LINGYUN.Abp.Rules.NRules/Microsoft/Extensions/DependencyInjection/NRulesServiceCollectionExtensions.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.Rules.NRules; +using NRules; +using NRules.Extensibility; +using NRules.Fluent; +using NRules.RuleModel; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class NRulesServiceCollectionExtensions + { + public static IServiceCollection AddNRules(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton((serviceProvider) => + { + return serviceProvider.GetRequiredService().Compile(); + }); + services.AddScoped((serviceProvider) => + { + return serviceProvider.GetRequiredService().CreateSession(); + }); + + return services; + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN.Abp.Rules.NRules.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN.Abp.Rules.NRules.Tests.csproj new file mode 100644 index 000000000..a5c9f0eb8 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN.Abp.Rules.NRules.Tests.csproj @@ -0,0 +1,27 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/AbpNRulesTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/AbpNRulesTestModule.cs new file mode 100644 index 000000000..21bb0340b --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/AbpNRulesTestModule.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Rules.NRules +{ + [DependsOn( + typeof(AbpNRulesModule))] + public class AbpNRulesTestModule : AbpModule + { + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInput.cs b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInput.cs new file mode 100644 index 000000000..20d2d818d --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInput.cs @@ -0,0 +1,13 @@ +namespace LINGYUN.Abp.Rules.NRules +{ + public class TestInput + { + public string Required { get; set; } + + public int Integer1 { get; set; } + + public int Integer2 { get; set; } + + public string Length { get; set; } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInputRule.cs b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInputRule.cs new file mode 100644 index 000000000..6ad83c5f4 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.NRules.Tests/LINGYUN/Abp/Rules/NRules/TestInputRule.cs @@ -0,0 +1,10 @@ +namespace LINGYUN.Abp.Rules.NRules +{ + public class TestInputRule : RuleBase + { + public override void Define() + { + // TODO: Test + } + } +}