Skip to content

Commit afa3f93

Browse files
committed
#6 - allow to assign to IType.Explanation by CustomRule
1 parent c9983cf commit afa3f93

File tree

6 files changed

+132
-1
lines changed

6 files changed

+132
-1
lines changed

sources/NetArchTest/Condition.cs

+19
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,24 @@ public ConditionList MeetCustomRule(Func<TypeDefinition, bool> rule)
214214
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
215215
return CreateConditionList();
216216
}
217+
/// <summary>
218+
/// Selects types that meet a custom rule.
219+
/// </summary>
220+
/// <param name="rule">An instance of the custom rule.</param>
221+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
222+
public ConditionList MeetCustomRule(ICustomRule2 rule)
223+
{
224+
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
225+
return CreateConditionList();
226+
}
227+
/// <summary>
228+
/// Selects types that meet a custom rule.
229+
/// </summary>
230+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
231+
public ConditionList MeetCustomRule(Func<TypeDefinition, CustomRuleResult> rule)
232+
{
233+
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
234+
return CreateConditionList();
235+
}
217236
}
218237
}

sources/NetArchTest/Functions/FunctionDelegates.cs

+37
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,42 @@ internal static IEnumerable<TypeSpec> MeetCustomRule(IEnumerable<TypeSpec> input
113113
return input.Where(t => !rule(t.Definition));
114114
}
115115
}
116+
117+
internal static IEnumerable<TypeSpec> MeetCustomRule(IEnumerable<TypeSpec> input, ICustomRule2 rule, bool condition)
118+
{
119+
var ruleDelegate = rule.MeetsRule;
120+
121+
if (condition)
122+
{
123+
return input.Where(t => ExecuteCustomRule(t, ruleDelegate));
124+
}
125+
else
126+
{
127+
return input.Where(t => !ExecuteCustomRule(t, ruleDelegate));
128+
}
129+
}
130+
131+
internal static IEnumerable<TypeSpec> MeetCustomRule(IEnumerable<TypeSpec> input, Func<TypeDefinition, CustomRuleResult> rule, bool condition)
132+
{
133+
if (condition)
134+
{
135+
return input.Where(t => ExecuteCustomRule(t, rule));
136+
}
137+
else
138+
{
139+
return input.Where(t => !ExecuteCustomRule(t, rule));
140+
}
141+
}
142+
143+
144+
private static bool ExecuteCustomRule(TypeSpec inputType, Func<TypeDefinition, CustomRuleResult> rule)
145+
{
146+
var result = rule.Invoke(inputType.Definition);
147+
if (!string.IsNullOrEmpty(result.Explanation))
148+
{
149+
inputType.Explanation = result.Explanation;
150+
}
151+
return result.IsMet;
152+
}
116153
}
117154
}

sources/NetArchTest/ICustomRule.cs

+30
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,34 @@ public interface ICustomRule
1414
/// <returns>The result of the test.</returns>
1515
bool MeetsRule(TypeDefinition type);
1616
}
17+
18+
19+
20+
/// <summary>
21+
/// An externally defined rule that can be applied as a condition or a predicate.
22+
/// </summary>
23+
public interface ICustomRule2
24+
{
25+
/// <summary>
26+
/// Tests whether the supplied type meets the rule.
27+
/// </summary>
28+
/// <param name="type">The type to be tested.</param>
29+
/// <returns>The result of the test.</returns>
30+
CustomRuleResult MeetsRule(TypeDefinition type);
31+
}
32+
33+
34+
public class CustomRuleResult
35+
{
36+
public bool IsMet { get; init; }
37+
38+
public string Explanation { get; init; }
39+
40+
41+
public CustomRuleResult(bool isMet, string explanation = null)
42+
{
43+
IsMet = isMet;
44+
Explanation = explanation;
45+
}
46+
}
1747
}

sources/NetArchTest/NetArchTest.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1717
<PackageId>NetArchTest.eNhancedEdition </PackageId>
1818
<PackageLicenseExpression>MIT</PackageLicenseExpression>
19-
<LangVersion>10</LangVersion>
19+
<LangVersion>11</LangVersion>
2020
<PackageReadmeFile>README.md</PackageReadmeFile>
2121
</PropertyGroup>
2222

sources/NetArchTest/Predicate.cs

+20
Original file line numberDiff line numberDiff line change
@@ -232,5 +232,25 @@ public PredicateList MeetCustomRule(Func<TypeDefinition, bool> rule)
232232
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
233233
return CreatePredicateList();
234234
}
235+
236+
/// <summary>
237+
/// Selects types that meet a custom rule.
238+
/// </summary>
239+
/// <param name="rule">An instance of the custom rule.</param>
240+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
241+
public PredicateList MeetCustomRule(ICustomRule2 rule)
242+
{
243+
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
244+
return CreatePredicateList();
245+
}
246+
/// <summary>
247+
/// Selects types that meet a custom rule.
248+
/// </summary>
249+
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
250+
public PredicateList MeetCustomRule(Func<TypeDefinition, CustomRuleResult> rule)
251+
{
252+
AddFunctionCall(x => FunctionDelegates.MeetCustomRule(x, rule, true));
253+
return CreatePredicateList();
254+
}
235255
}
236256
}

tests/NetArchTest.Rules.UnitTests/PredicateTests.cs

+25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq;
33
using System.Reflection;
4+
using Mono.Cecil;
45
using NetArchTest.CrossAssemblyTest.A;
56
using NetArchTest.CrossAssemblyTest.B;
67
using NetArchTest.Rules;
@@ -284,5 +285,29 @@ public void MeetCustomRule()
284285
// The custom rule was executed at least once
285286
Assert.True(rule.TestMethodCalled);
286287
}
288+
289+
[Fact(DisplayName = "MeetCustomRule2")]
290+
public void MeetCustomRule2()
291+
{
292+
// Create a custom rule that selects "ClassA1"
293+
Func <TypeDefinition, CustomRuleResult> rule = t => new CustomRuleResult(t.Name.Equals("ClassA3", StringComparison.InvariantCultureIgnoreCase), "yup");
294+
295+
// Use the custom rule
296+
var result = fixture.Types
297+
.That()
298+
.MeetCustomRule(rule)
299+
.GetTypes();
300+
301+
302+
// ClassA1 has been returned
303+
Assert.Single(result);
304+
305+
var first = result.First();
306+
307+
Assert.Equal<Type>(typeof(ClassA3), first.ReflectionType);
308+
Assert.Equal("yup", first.Explanation);
309+
310+
311+
}
287312
}
288313
}

0 commit comments

Comments
 (0)