Skip to content

Commit 59bd09e

Browse files
committed
Feat: initial import from code-of-chaos.cs
1 parent 74a491a commit 59bd09e

File tree

7 files changed

+297
-0
lines changed

7 files changed

+297
-0
lines changed

CodeOfChaos.Extensions.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{AF1A203C
1212
EndProject
1313
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools.CodeOfChaos.Extensions", "src\Tools.CodeOfChaos.Extensions\Tools.CodeOfChaos.Extensions.csproj", "{ADEADD97-0AFA-4D9E-970B-9FFB932949B3}"
1414
EndProject
15+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeOfChaos.Extensions.EntityFrameworkCore", "src\CodeOfChaos.Extensions.EntityFrameworkCore\CodeOfChaos.Extensions.EntityFrameworkCore.csproj", "{411473A5-2921-4758-B78C-E66BCFFE6303}"
16+
EndProject
17+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.CodeOfChaos.Extensions.EntityFrameworkCore", "tests\Tests.CodeOfChaos.Extensions.EntityFrameworkCore\Tests.CodeOfChaos.Extensions.EntityFrameworkCore.csproj", "{0A198DE2-E404-4BC4-9C6C-A4E1B4397463}"
18+
EndProject
1519
Global
1620
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1721
Debug|Any CPU = Debug|Any CPU
@@ -30,10 +34,20 @@ Global
3034
{ADEADD97-0AFA-4D9E-970B-9FFB932949B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
3135
{ADEADD97-0AFA-4D9E-970B-9FFB932949B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
3236
{ADEADD97-0AFA-4D9E-970B-9FFB932949B3}.Release|Any CPU.Build.0 = Release|Any CPU
37+
{411473A5-2921-4758-B78C-E66BCFFE6303}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38+
{411473A5-2921-4758-B78C-E66BCFFE6303}.Debug|Any CPU.Build.0 = Debug|Any CPU
39+
{411473A5-2921-4758-B78C-E66BCFFE6303}.Release|Any CPU.ActiveCfg = Release|Any CPU
40+
{411473A5-2921-4758-B78C-E66BCFFE6303}.Release|Any CPU.Build.0 = Release|Any CPU
41+
{0A198DE2-E404-4BC4-9C6C-A4E1B4397463}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42+
{0A198DE2-E404-4BC4-9C6C-A4E1B4397463}.Debug|Any CPU.Build.0 = Debug|Any CPU
43+
{0A198DE2-E404-4BC4-9C6C-A4E1B4397463}.Release|Any CPU.ActiveCfg = Release|Any CPU
44+
{0A198DE2-E404-4BC4-9C6C-A4E1B4397463}.Release|Any CPU.Build.0 = Release|Any CPU
3345
EndGlobalSection
3446
GlobalSection(NestedProjects) = preSolution
3547
{26284571-0E09-4BAF-8C2B-DF87DCC1BA0B} = {8DD280D4-1E14-4D5E-AFE6-58DD8F079DCC}
3648
{64B26DED-68C3-47FF-B409-1C8FAD4F9176} = {197E72AD-DEAB-4350-AFC3-A3BB38720BF5}
3749
{ADEADD97-0AFA-4D9E-970B-9FFB932949B3} = {AF1A203C-6EF1-440E-BB3C-55B1DBFE9C19}
50+
{411473A5-2921-4758-B78C-E66BCFFE6303} = {197E72AD-DEAB-4350-AFC3-A3BB38720BF5}
51+
{0A198DE2-E404-4BC4-9C6C-A4E1B4397463} = {8DD280D4-1E14-4D5E-AFE6-58DD8F079DCC}
3852
EndGlobalSection
3953
EndGlobal
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
11+
</ItemGroup>
12+
13+
</Project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using Microsoft.EntityFrameworkCore;
5+
// ReSharper disable once CheckNamespace
6+
namespace System.Linq.Expressions;
7+
// ---------------------------------------------------------------------------------------------------------------------
8+
// Code
9+
// ---------------------------------------------------------------------------------------------------------------------
10+
public static class LinqExtensions {
11+
12+
public static IQueryable<T> ConditionalInclude<T>(this IQueryable<T> source, bool condition, Expression<Func<T, object>> include) where T : class
13+
=> condition
14+
? source.Include(include)
15+
: source;
16+
17+
18+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
// ReSharper disable once CheckNamespace
5+
namespace System.Linq.Expressions;
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public static class LinqExtensions {
10+
11+
public static IQueryable<T> ConditionalWhere<T>(this IQueryable<T> source, bool condition, Expression<Func<T, bool>> predicate)
12+
=> condition
13+
? source.Where(predicate)
14+
: source;
15+
16+
public static IQueryable<T> ConditionalTake<T>(this IQueryable<T> source, bool condition, int count)
17+
=> condition && count > 0
18+
? source.Take(count)
19+
: source;
20+
21+
public static IQueryable<T> ConditionalTake<T>(this IQueryable<T> source, bool condition, Range range)
22+
=> condition
23+
? source.Take(range)
24+
: source;
25+
26+
public static IQueryable<T> ConditionalOrderBy<T>(this IQueryable<T> source, bool condition, Expression<Func<T, object>> orderBy)
27+
=> condition
28+
? source.OrderBy(orderBy)
29+
: source;
30+
31+
public static IQueryable<T> ConditionalSkip<T>(this IQueryable<T> source, bool condition, int count)
32+
=> condition && count > 0
33+
? source.Skip(count)
34+
: source;
35+
36+
public static IQueryable<TSource> ConditionalOrderBy<TSource, TKey>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, TKey>> orderBy, IComparer<TKey>? comparer)
37+
=> condition
38+
? source.OrderBy(orderBy, comparer)
39+
: source;
40+
41+
public static IQueryable<TSource> ConditionalOrderByNotNull<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>>? orderBy)
42+
=> orderBy is not null
43+
? source.OrderBy(orderBy)
44+
: source;
45+
46+
public static IQueryable<TSource> ConditionalOrderByNotNull<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>>? orderBy, IComparer<TKey>? comparer)
47+
=> orderBy is not null
48+
? source.OrderBy(orderBy,comparer)
49+
: source;
50+
51+
public static IQueryable<TSource> ConditionalQuery<TSource>(this IQueryable<TSource> source, bool condition, Func<IQueryable<TSource>, IQueryable<TSource>> queryableFunc)
52+
=> condition
53+
? queryableFunc(source)
54+
: source;
55+
56+
public static IQueryable<T> ConditionalDistinct<T>(this IQueryable<T> source, bool condition)
57+
=> condition
58+
? source.Distinct()
59+
: source;
60+
61+
public static IQueryable<T> ConditionalUnion<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
62+
=> condition
63+
? source.Union(second)
64+
: source;
65+
66+
public static IQueryable<T> ConditionalIntersect<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
67+
=> condition
68+
? source.Intersect(second)
69+
: source;
70+
71+
public static IQueryable<T> ConditionalExcept<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
72+
=> condition
73+
? source.Except(second)
74+
: source;
75+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<LangVersion>latest</LangVersion>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Bogus" Version="35.6.1"/>
13+
<PackageReference Include="TUnit" Version="0.4.105" />
14+
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0"/>
15+
<PackageReference Include="coverlet.collector" Version="6.0.2"/>
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
17+
</ItemGroup>
18+
19+
</Project>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using JetBrains.Annotations;
5+
using System.Linq.Expressions;
6+
using TUnit.Assertions;
7+
using TUnit.Assertions.Extensions;
8+
using TUnit.Core;
9+
10+
namespace Tests.CodeOfChaos.Extensions;
11+
// ---------------------------------------------------------------------------------------------------------------------
12+
// Code
13+
// ---------------------------------------------------------------------------------------------------------------------
14+
[TestSubject(typeof(LinqExtensions))]
15+
public class LinqExtensionsTests {
16+
private readonly List<int> _data = Enumerable.Range(1, 10).ToList();// Data: {1, 2, 3, ... 10}
17+
18+
[Test]
19+
public async Task ConditionalWhere_ConditionTrue_ShouldFilter() {
20+
IQueryable<int> source = _data.AsQueryable();
21+
List<int> result = source.ConditionalWhere(true, predicate: x => x > 5).ToList();
22+
23+
await Assert.That(result).IsEqualTo([
24+
6, 7, 8, 9, 10
25+
]);
26+
}
27+
28+
[Test]
29+
public async Task ConditionalWhere_ConditionFalse_ShouldNotFilter() {
30+
IQueryable<int> source = _data.AsQueryable();
31+
List<int> result = source.ConditionalWhere(false, predicate: x => x > 5).ToList();
32+
33+
await Assert.That(result).IsEqualTo(_data);
34+
}
35+
36+
[Test]
37+
public async Task ConditionalTake_ConditionTrue_ShouldTakeElements() {
38+
IQueryable<int> source = _data.AsQueryable();
39+
List<int> result = source.ConditionalTake(true, 5).ToList();
40+
41+
await Assert.That(result).IsEqualTo([
42+
1, 2, 3, 4, 5
43+
]);
44+
}
45+
46+
[Test]
47+
public async Task ConditionalTake_ConditionFalse_ShouldNotTakeElements() {
48+
IQueryable<int> source = _data.AsQueryable();
49+
List<int> result = source.ConditionalTake(false, 5).ToList();
50+
51+
await Assert.That(result).IsEqualTo(_data);
52+
}
53+
54+
[Test]
55+
public async Task ConditionalOrderBy_ConditionTrue_ShouldOrder() {
56+
IQueryable<int> source = _data.AsQueryable();
57+
List<int> result = source.ConditionalOrderBy(true, orderBy: x => -x).ToList();
58+
59+
await Assert.That(result).IsEqualTo([
60+
10, 9, 8, 7, 6, 5, 4, 3, 2, 1
61+
]);
62+
}
63+
64+
[Test]
65+
public async Task ConditionalOrderBy_ConditionFalse_ShouldNotOrder() {
66+
IQueryable<int> source = _data.AsQueryable();
67+
List<int> result = source.ConditionalOrderBy(false, orderBy: x => -x).ToList();
68+
69+
await Assert.That(result).IsEqualTo(_data);
70+
}
71+
72+
[Test]
73+
public async Task ConditionalSkip_ConditionTrue_ShouldSkipElements() {
74+
IQueryable<int> source = _data.AsQueryable();
75+
List<int> result = source.ConditionalSkip(true, 5).ToList();
76+
77+
await Assert.That(result).IsEqualTo([
78+
6, 7, 8, 9, 10
79+
]);
80+
}
81+
82+
[Test]
83+
public async Task ConditionalSkip_ConditionFalse_ShouldNotSkipElements() {
84+
IQueryable<int> source = _data.AsQueryable();
85+
List<int> result = source.ConditionalSkip(false, 5).ToList();
86+
87+
await Assert.That(result).IsEqualTo(_data);
88+
}
89+
90+
[Test]
91+
public async Task ConditionalDistinct_ConditionTrue_ShouldReturnDistinct() {
92+
IQueryable<int> source = new List<int> { 1, 2, 2, 3, 3, 3 }.AsQueryable();
93+
List<int> result = source.ConditionalDistinct(true).ToList();
94+
95+
await Assert.That(result).IsEqualTo([
96+
1, 2, 3
97+
]);
98+
}
99+
100+
[Test]
101+
public async Task ConditionalDistinct_ConditionFalse_ShouldReturnOriginal() {
102+
IQueryable<int> source = new List<int> { 1, 2, 2, 3, 3, 3 }.AsQueryable();
103+
List<int> result = source.ConditionalDistinct(false).ToList();
104+
105+
await Assert.That(result).IsEqualTo([
106+
1, 2, 2, 3, 3, 3
107+
]);
108+
}
109+
110+
[Test]
111+
public async Task ConditionalUnion_ConditionTrue_ShouldUnion() {
112+
IQueryable<int> source = new List<int> { 1, 2, 3 }.AsQueryable();
113+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
114+
List<int> result = source.ConditionalUnion(true, second).ToList();
115+
116+
await Assert.That(result).IsEqualTo([
117+
1, 2, 3, 4, 5
118+
]);
119+
}
120+
121+
[Test]
122+
public async Task ConditionalUnion_ConditionFalse_ShouldNotUnion() {
123+
IQueryable<int> source = new List<int> { 1, 2, 3 }.AsQueryable();
124+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
125+
List<int> result = source.ConditionalUnion(false, second).ToList();
126+
127+
await Assert.That(result).IsEqualTo([
128+
1, 2, 3
129+
]);
130+
}
131+
132+
[Test]
133+
public async Task ConditionalExcept_ConditionTrue_ShouldApplyExcept() {
134+
IQueryable<int> source = new List<int> { 1, 2, 3, 4 }.AsQueryable();
135+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
136+
List<int> result = source.ConditionalExcept(true, second).ToList();
137+
138+
await Assert.That(result).IsEqualTo([
139+
1, 2
140+
]);
141+
}
142+
143+
[Test]
144+
public async Task ConditionalExcept_ConditionFalse_ShouldNotApplyExcept() {
145+
IQueryable<int> source = new List<int> { 1, 2, 3, 4 }.AsQueryable();
146+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
147+
List<int> result = source.ConditionalExcept(false, second).ToList();
148+
149+
await Assert.That(result).IsEqualTo([
150+
1, 2, 3, 4
151+
]);
152+
}
153+
}

tests/Tests.CodeOfChaos.Extensions/Tests.CodeOfChaos.Extensions.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
910
</PropertyGroup>
1011

1112
<ItemGroup>
@@ -16,4 +17,8 @@
1617
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1718
</ItemGroup>
1819

20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\CodeOfChaos.Extensions\CodeOfChaos.Extensions.csproj" />
22+
</ItemGroup>
23+
1924
</Project>

0 commit comments

Comments
 (0)