Skip to content

Commit 2bd7246

Browse files
authored
Fix ArgumentNullException for InMemoryRulesStorage from IServiceCollection (#142)
* fix: resolve wrong type resolution when using service provider to get in-memory rules storage * fix: fix failing tests * refactor: adjusted extensions namespaces for simplicity of use for consumers * refactor: moved unit tests for in-memory provider to Rules.Framework.Tests * fix: fix codacy reported issues * fix: fix tests from merge (remove simplified data source implementation)
1 parent 20cb7c2 commit 2bd7246

26 files changed

Lines changed: 252 additions & 292 deletions

rules-framework.sln

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Integration
2828
EndProject
2929
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Providers.InMemory.IntegrationTests", "tests\Rules.Framework.Providers.InMemory.IntegrationTests\Rules.Framework.Providers.InMemory.IntegrationTests.csproj", "{69BBA04D-116C-48EA-A8FD-ECC8CA0D57BE}"
3030
EndProject
31-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Providers.InMemory.Tests", "tests\Rules.Framework.Providers.InMemory.Tests\Rules.Framework.Providers.InMemory.Tests.csproj", "{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4}"
32-
EndProject
3331
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{3125C5B5-0FD5-4370-9E22-A44A3BCEED59}"
3432
EndProject
3533
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.InMemory.Sample", "samples\Rules.Framework.InMemory.Sample\Rules.Framework.InMemory.Sample.csproj", "{DB242766-733B-4073-B20C-E2AA6D13DB8C}"
@@ -40,7 +38,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.WebUI", "sr
4038
EndProject
4139
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.WebUI.Tests", "tests\Rules.Framework.WebUI.Tests\Rules.Framework.WebUI.Tests.csproj", "{29DC6661-4F0C-46F7-AC91-968700D13C11}"
4240
EndProject
43-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rules.Framework.BenchmarkTests", "tests\Rules.Framework.BenchmarkTests\Rules.Framework.BenchmarkTests.csproj", "{16C9F383-3B58-4911-9D26-7FDB907DD0D2}"
41+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.BenchmarkTests", "tests\Rules.Framework.BenchmarkTests\Rules.Framework.BenchmarkTests.csproj", "{16C9F383-3B58-4911-9D26-7FDB907DD0D2}"
4442
EndProject
4543
Global
4644
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -80,10 +78,6 @@ Global
8078
{69BBA04D-116C-48EA-A8FD-ECC8CA0D57BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
8179
{69BBA04D-116C-48EA-A8FD-ECC8CA0D57BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
8280
{69BBA04D-116C-48EA-A8FD-ECC8CA0D57BE}.Release|Any CPU.Build.0 = Release|Any CPU
83-
{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
84-
{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
85-
{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
86-
{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4}.Release|Any CPU.Build.0 = Release|Any CPU
8781
{DB242766-733B-4073-B20C-E2AA6D13DB8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8882
{DB242766-733B-4073-B20C-E2AA6D13DB8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
8983
{DB242766-733B-4073-B20C-E2AA6D13DB8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -117,7 +111,6 @@ Global
117111
{C2957B7C-D601-4850-BCCE-D9AEF07225AB} = {74E24C97-8EE4-4B69-AECD-4765FD2C751F}
118112
{7C04ECEF-6504-453D-ABD8-FD3D5A2CF7F6} = {74E24C97-8EE4-4B69-AECD-4765FD2C751F}
119113
{69BBA04D-116C-48EA-A8FD-ECC8CA0D57BE} = {74E24C97-8EE4-4B69-AECD-4765FD2C751F}
120-
{BB319C5B-9BF5-4DDB-B522-CFC64D7272C4} = {74E24C97-8EE4-4B69-AECD-4765FD2C751F}
121114
{DB242766-733B-4073-B20C-E2AA6D13DB8C} = {3125C5B5-0FD5-4370-9E22-A44A3BCEED59}
122115
{F5E1BEF6-85CD-4966-94C2-DCA02D824043} = {3125C5B5-0FD5-4370-9E22-A44A3BCEED59}
123116
{7CE82611-FEC1-49E9-91FB-4C3ADF5ED56F} = {AEE746EC-CEAA-4892-8C29-0CAAB97A23A8}

src/Rules.Framework/Providers/InMemory/InMemoryProviderRulesDataSourceSelectorExtensions.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
namespace Rules.Framework.Providers.InMemory
1+
namespace Rules.Framework
22
{
33
using System;
44
using Rules.Framework.Builder;
5+
using Rules.Framework.Providers.InMemory;
56

67
/// <summary>
78
/// Rules data source selector extensions from in-memory provider.
@@ -15,9 +16,7 @@ public static class InMemoryProviderRulesDataSourceSelectorExtensions
1516
/// <typeparam name="TConditionType">The type of the condition type.</typeparam>
1617
/// <param name="rulesDataSourceSelector">The rules data source selector.</param>
1718
/// <returns></returns>
18-
/// <exception cref="ArgumentNullException">
19-
/// rulesDataSourceSelector
20-
/// </exception>
19+
/// <exception cref="ArgumentNullException">rulesDataSourceSelector</exception>
2120
public static IConfiguredRulesEngineBuilder<TContentType, TConditionType> SetInMemoryDataSource<TContentType, TConditionType>(
2221
this IRulesDataSourceSelector<TContentType, TConditionType> rulesDataSourceSelector)
2322
=> rulesDataSourceSelector.SetInMemoryDataSource(new InMemoryRulesStorage<TContentType, TConditionType>());
@@ -30,11 +29,7 @@ public static IConfiguredRulesEngineBuilder<TContentType, TConditionType> SetInM
3029
/// <param name="rulesDataSourceSelector">The rules data source selector.</param>
3130
/// <param name="serviceProvider">The service provider.</param>
3231
/// <returns></returns>
33-
/// <exception cref="ArgumentNullException">
34-
/// rulesDataSourceSelector
35-
/// or
36-
/// serviceProvider
37-
/// </exception>
32+
/// <exception cref="ArgumentNullException">rulesDataSourceSelector or serviceProvider</exception>
3833
public static IConfiguredRulesEngineBuilder<TContentType, TConditionType> SetInMemoryDataSource<TContentType, TConditionType>(
3934
this IRulesDataSourceSelector<TContentType, TConditionType> rulesDataSourceSelector,
4035
IServiceProvider serviceProvider)
@@ -44,8 +39,8 @@ public static IConfiguredRulesEngineBuilder<TContentType, TConditionType> SetInM
4439
throw new ArgumentNullException(nameof(serviceProvider));
4540
}
4641

47-
IInMemoryRulesStorage<TContentType, TConditionType> inMemoryRulesStorage = serviceProvider
48-
.GetService(typeof(InMemoryRulesStorage<TContentType, TConditionType>)) as InMemoryRulesStorage<TContentType, TConditionType>;
42+
var inMemoryRulesStorage = (IInMemoryRulesStorage<TContentType, TConditionType>)serviceProvider
43+
.GetService(typeof(IInMemoryRulesStorage<TContentType, TConditionType>));
4944

5045
return rulesDataSourceSelector.SetInMemoryDataSource(inMemoryRulesStorage);
5146
}
@@ -59,8 +54,8 @@ private static IConfiguredRulesEngineBuilder<TContentType, TConditionType> SetIn
5954
throw new ArgumentNullException(nameof(rulesDataSourceSelector));
6055
}
6156

62-
IRuleFactory<TContentType, TConditionType> ruleFactory = new RuleFactory<TContentType, TConditionType>();
63-
InMemoryProviderRulesDataSource<TContentType, TConditionType> inMemoryProviderRulesDataSource
57+
var ruleFactory = new RuleFactory<TContentType, TConditionType>();
58+
var inMemoryProviderRulesDataSource
6459
= new InMemoryProviderRulesDataSource<TContentType, TConditionType>(inMemoryRulesStorage, ruleFactory);
6560

6661
return rulesDataSourceSelector.SetDataSource(inMemoryProviderRulesDataSource);

src/Rules.Framework/Providers/InMemory/ServiceCollectionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
namespace Rules.Framework.Providers.InMemory
1+
namespace Microsoft.Extensions.DependencyInjection
22
{
3-
using Microsoft.Extensions.DependencyInjection;
3+
using Rules.Framework.Providers.InMemory;
44

55
/// <summary>
66
/// Service collection extensions from in-memory provider.

tests/Rules.Framework.IntegrationTests/InMemoryRulesDataSource.cs

Lines changed: 0 additions & 70 deletions
This file was deleted.

tests/Rules.Framework.IntegrationTests/Rules.Framework.IntegrationTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
</PackageReference>
1414
<PackageReference Include="ExpressionTranslator" Version="2.5.0" />
1515
<PackageReference Include="FluentAssertions" Version="6.10.0" />
16+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
1617
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
1718
<PackageReference Include="xunit" Version="2.4.2" />
1819
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">

tests/Rules.Framework.IntegrationTests/RulesFromJsonFile.cs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,27 @@ namespace Rules.Framework.IntegrationTests
44
using System.Collections.Generic;
55
using System.Globalization;
66
using System.IO;
7-
using System.Linq;
87
using System.Threading.Tasks;
98
using Newtonsoft.Json;
109
using Rules.Framework.Builder;
1110
using Rules.Framework.Core;
1211
using Rules.Framework.IntegrationTests.DataSource;
13-
using Rules.Framework.Serialization;
1412

1513
internal class RulesFromJsonFile
1614
{
1715
private static readonly RulesFromJsonFile instance = new RulesFromJsonFile();
1816

1917
public static RulesFromJsonFile Load => instance;
2018

21-
public async Task<IRulesDataSource<TContentType, TConditionType>> FromJsonFileAsync<TContentType, TConditionType>(string filePath, bool serializedContent = true)
19+
public async Task FromJsonFileAsync<TContentType, TConditionType>(RulesEngine<TContentType, TConditionType> rulesEngine, string filePath, Type contentRuntimeType, bool serializedContent = true)
2220
where TContentType : new()
2321
{
24-
var serializationProvider = new JsonContentSerializationProvider<TContentType>();
25-
2622
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
2723
using (var streamReader = new StreamReader(fileStream))
2824
{
2925
var contents = await streamReader.ReadToEndAsync();
3026
var ruleDataModels = await Task.Run(() => JsonConvert.DeserializeObject<IEnumerable<RuleDataModel>>(contents));
3127

32-
var rules = new List<Rule<TContentType, TConditionType>>(ruleDataModels.Count());
3328
foreach (var ruleDataModel in ruleDataModels)
3429
{
3530
var contentType = GetContentType<TContentType>(ruleDataModel.ContentTypeCode);
@@ -43,30 +38,29 @@ public async Task<IRulesDataSource<TContentType, TConditionType>> FromJsonFileAs
4338
ruleBuilder.WithCondition(b => this.ConvertConditionNode(b, ruleDataModel.RootCondition));
4439
}
4540

41+
object content;
4642
if (serializedContent)
4743
{
48-
ruleBuilder.WithSerializedContent(contentType, ruleDataModel.Content, serializationProvider);
44+
content = JsonConvert.DeserializeObject(ruleDataModel.Content, contentRuntimeType);
4945
}
5046
else
5147
{
52-
ruleBuilder.WithContentContainer(new ContentContainer<TContentType>(contentType, (t) => RulesFromJsonFile.Parse(ruleDataModel.Content, t)));
48+
content = RulesFromJsonFile.Parse(ruleDataModel.Content, contentRuntimeType);
5349
}
5450

51+
ruleBuilder.WithContentContainer(new ContentContainer<TContentType>(contentType, (_) => content));
5552
var ruleBuilderResult = ruleBuilder.Build();
5653

5754
if (ruleBuilderResult.IsSuccess)
5855
{
5956
var rule = ruleBuilderResult.Rule;
60-
rule.Priority = ruleDataModel.Priority;
61-
rules.Add(rule);
57+
await rulesEngine.AddRuleAsync(rule, RuleAddPriorityOption.ByPriorityNumber(ruleDataModel.Priority));
6258
}
6359
else
6460
{
6561
throw new InvalidRuleException($"Loaded invalid rule from file. Rule name: {ruleDataModel.Name}");
6662
}
6763
}
68-
69-
return new InMemoryRulesDataSource<TContentType, TConditionType>(rules);
7064
}
7165
}
7266

0 commit comments

Comments
 (0)