### Configure Dependency Analysis with Predicates Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Use these C# code examples to filter types based on their dependencies. Examples demonstrate specifying single or multiple dependencies, using 'any' or 'all' logic, and whitelisting or prohibiting specific dependencies. ```csharp // Single dependency Types.InCurrentDomain() .That().HaveDependencyOn("System.Data") // Multiple dependencies (any) .That().HaveDependencyOnAny("System.Data", "EntityFramework") // Multiple dependencies (all required) .That().HaveDependencyOnAll("System.Collections", "System.Linq") // Whitelist dependencies .That().OnlyHaveDependenciesOn("System", "MyApp.Common") // Prohibited dependencies .That().HaveDependenciesOtherThan("System.Reflection", "System.Linq") ``` -------------------------------- ### HaveNameStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that type names start with specified text. ```APIDOC ## HaveNameStartingWith(string start) ### Description Asserts that type names start with specified text. ### Method public ConditionList HaveNameStartingWith(string start) ### Parameters #### Path Parameters - **start** (string) - Required - Name prefix ### Response #### Success Response (ConditionList) - Returns an updated `ConditionList` for chaining. ### Request Example ```csharp var result = Types.InCurrentDomain() .That().AreInterfaces() .Should().HaveNameStartingWith("I") .GetResult(); ``` ``` -------------------------------- ### Naming Convention: Interfaces Start with I Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Verifies that all interfaces defined in the project start with the prefix 'I'. This is a standard naming convention for interfaces. ```csharp // Interfaces start with I Types.InCurrentDomain() .That().AreInterfaces() .Should().HaveNameStartingWith("I") .GetResult(); ``` -------------------------------- ### Example: Assert No Dependency on Specific Namespace (C#) Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md This example demonstrates how to use the `ResideInNamespace` and `HaveDependencyOn` conditions to ensure types in a specific namespace do not depend on another namespace. It chains conditions and retrieves the result. ```csharp Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Presentation") .ShouldNot().HaveDependencyOn("MyApp.Data") .GetResult(); ``` -------------------------------- ### Type Dependencies - Entry Point Flow Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/types.md Illustrates the flow of type dependencies starting from the entry point, through types, predicates, conditions, and finally to custom rules. ```text Entry Point ↓ Types ─→ Predicates ─→ PredicateList ↓ ↓ (filter) Should() / ShouldNot() ↓ ↓ Conditions ← ConditionList ↓ ↓ (assert) GetResult() / Count() ↓ ↓ ICustomRule TestResult ``` -------------------------------- ### Fluent API Chain Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/INDEX.md Illustrates the typical chain of operations in the NetArchTest fluent API, from selecting types to evaluating results. ```text Types (select types) ↓ .That() → Predicates (filter) ↓ PredicateList (and/or) ↓ .Should() / .ShouldNot() → Conditions (assert) ↓ ConditionList (and/or) ↓ .GetResult() / .GetTypes() / .Count() → Results ``` -------------------------------- ### XUnit: Interfaces Should Start With 'I' Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Enforce naming conventions for interfaces, ensuring they all begin with the prefix 'I'. This promotes consistency in interface definitions. ```csharp [Fact] public void Interfaces_Should_Start_With_I() { var result = Types.InCurrentDomain() .That() .AreInterfaces() .And() .ArePublic() .Should() .HaveNameStartingWith("I") .GetResult(); Assert.True(result.IsSuccessful); } ``` -------------------------------- ### Example Regex Patterns Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Demonstrates common regular expression patterns for matching names and namespaces. Case-insensitive matching is always applied. ```csharp // Match names starting with I or Abstract @"^(I|Abstract)\w+" ``` ```csharp // Match namespace containing Service @".*Service.*" ``` ```csharp // Match names ending with Repository or Handler @"\w+(Repository|Handler)$" ``` -------------------------------- ### HaveNameStartingWith Condition Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that type names start with specified text. Useful for checking common prefixes like interface naming conventions. ```csharp var result = Types.InCurrentDomain() .That().AreInterfaces() .Should().HaveNameStartingWith("I") .GetResult(); ``` -------------------------------- ### HaveNameStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Selects types whose names start with text using specified comparison rules. ```APIDOC ## HaveNameStartingWith(string, StringComparison) ### Description Selects types whose names start with text using specified comparison rules. ### Method `Predicates.HaveNameStartingWith` ### Parameters #### Path Parameters - **start** (string) - Required - Name prefix to match - **comparer** (StringComparison) - Required - String comparison rules (e.g., Ordinal, OrdinalIgnoreCase) ### Request Example ```csharp types.That().HaveNameStartingWith("Service", StringComparison.OrdinalIgnoreCase).Should().BeAbstract().GetResult(); ``` ``` -------------------------------- ### Evaluate Policy and Check for Violations Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/policies.md This example shows how to define a policy, add rules, and then evaluate it. It demonstrates checking the results for any violations and iterating through them to display details about failed rules and types. ```csharp var policy = Policy.Define("Architecture", "Layered architecture") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .ResideInNamespace("MyApp.Presentation") .ShouldNot() .HaveDependencyOn("MyApp.Data"), "Presentation should not reference Data") .Add(t => t.That() .AreInterfaces() .Should() .HaveNameStartingWith("I"), "Interfaces start with I"); var results = policy.Evaluate(); if (results.HasViolations) { Console.WriteLine($"Policy '{results.Name}' has violations:"); foreach (var result in results.Results.Where(r => !r.IsSuccessful)) { Console.WriteLine($" - {result.Name}: {result.FailingTypes.Count()} types failed"); } } ``` -------------------------------- ### HaveNameStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Selects types whose names start with specified text. ```APIDOC ## HaveNameStartingWith(params string[]) ### Description Selects types whose names start with specified text. ### Method `Predicates.HaveNameStartingWith` ### Parameters #### Path Parameters - **start** (string[]) - Required - One or more name prefixes to match ### Request Example ```csharp types.That().HaveNameStartingWith("I").AreInterfaces().GetTypes(); ``` ``` -------------------------------- ### Filtering Predicates Examples Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/INDEX.md Shows examples of predicates used to filter types based on various criteria like name, type, inheritance, scope, namespace, dependencies, attributes, and immutability. ```csharp HaveName HaveNameStartingWith HaveNameMatching AreClasses AreInterfaces AreAbstract AreSealed Inherit ImplementInterface ArePublic AreNested AreStatic ResideInNamespace ResideInNamespaceMatching HaveDependencyOn OnlyHaveDependenciesOn HaveCustomAttribute HaveCustomAttributeOrInherit AreImmutable AreMutable MeetCustomRule ``` -------------------------------- ### Assertion Conditions Examples Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/INDEX.md Provides examples of assertion conditions for checking type properties, including name, type, inheritance, namespace, dependencies, and attributes. Supports both positive ('Should()') and negative ('ShouldNot()') assertions. ```csharp Should() ShouldNot() ``` -------------------------------- ### Policy with Multiple Architectural Rules Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/README.md This example shows how to group multiple architectural rules into a single policy for comprehensive testing. It includes rules for interface naming conventions and service sealing. ```csharp using NetArchTest.Rules; // Policy with multiple rules var policy = Policy.Define("Architecture", "Layered architecture rules") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .AreInterfaces() .Should() .HaveNameStartingWith("I"), "Interface naming") .Add(t => t.That() .HaveNameEndingWith("Service") .Should() .BeSealed(), "Service sealing"); var results = policy.Evaluate(); ``` -------------------------------- ### NotHaveNameStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that type names do not start with specified text. ```APIDOC ## NotHaveNameStartingWith(string start) ### Description Asserts that type names do not start with specified text. ### Method public ConditionList NotHaveNameStartingWith(string start) ### Parameters #### Path Parameters - **start** (string) - Required - Name prefix to exclude ### Response #### Success Response (ConditionList) - Returns an updated `ConditionList` for chaining. ``` -------------------------------- ### HaveNameStartingWith with StringComparison Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts type names start with text using specified comparison rules. ```APIDOC ## HaveNameStartingWith(string start, StringComparison comparer) ### Description Asserts type names start with text using specified comparison rules. ### Method public ConditionList HaveNameStartingWith(string start, StringComparison comparer) ### Parameters #### Path Parameters - **start** (string) - Required - Name prefix - **comparer** (StringComparison) - Required - String comparison rules ### Response #### Success Response (ConditionList) - Returns an updated `ConditionList` for chaining. ``` -------------------------------- ### TestResult Usage Examples Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Examples demonstrating how to use the TestResult class to check test outcomes and report failing types. ```APIDOC ## Usage Patterns ### Basic Test Assertion ```csharp var result = Types.InCurrentDomain() .That().AreClasses() .Should().BePublic() .GetResult(); Assert.True(result.IsSuccessful, $"Expected all classes to be public, but {result.FailingTypes.Count} were not."); ``` ### Reporting Failed Types ```csharp var result = Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Services") .Should().HaveNameEndingWith("Service") .GetResult(); if (!result.IsSuccessful) { Console.WriteLine("Classes that don't end with 'Service':"); foreach (var name in result.FailingTypeNames) { Console.WriteLine($" - {name}"); } } ``` ### Filtering Results ```csharp var result = Types.InCurrentDomain() .That().AreClasses() .Should().Inherit(typeof(EntityBase)) .GetResult(); var failingClassNames = result.FailingTypeNames .Where(t => !t.Contains("Test")) .ToList(); if (failingClassNames.Any()) { Console.WriteLine("Non-test classes not inheriting from EntityBase:"); foreach (var name in failingClassNames) { Console.WriteLine($" - {name}"); } } ``` ``` -------------------------------- ### Reporting Failed Types Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Report on classes that do not end with 'Service' within a specific namespace. This example checks the IsSuccessful property and iterates through FailingTypeNames to print the names of the non-compliant types. ```csharp var result = Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Services") .Should().HaveNameEndingWith("Service") .GetResult(); if (!result.IsSuccessful) { Console.WriteLine("Classes that don't end with 'Service':"); foreach (var name in result.FailingTypeNames) { Console.WriteLine($" - {name}"); } } ``` -------------------------------- ### NotHaveNameStartingWith Condition Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that type names do not start with specified text. Use this to ensure types do not have a particular prefix. ```csharp public ConditionList NotHaveNameStartingWith(string start) ``` -------------------------------- ### Check Class Dependencies and Namespace Implementation Source: https://github.com/benmorris/netarchtest/blob/master/README.md Verify that classes with a dependency on System.Data and residing in the 'ArchTest' namespace also reside in the 'NetArchTest.SampleLibrary.Data' namespace. This example combines dependency checks with namespace residency. ```csharp // Classes in the "data" namespace should implement IRepository result = Types.InCurrentDomain() .That().HaveDependencyOn("System.Data") .And().ResideInNamespace(("ArchTest")) .Should().ResideInNamespace(("NetArchTest.SampleLibrary.Data")) .GetResult() .IsSuccessful; ``` -------------------------------- ### Complete Policy Evaluation Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/policies.md Defines a policy with multiple rules, evaluates it against types in the current domain, and then iterates through the results to report on policy and rule outcomes, including any failing types. ```csharp var architecturePolicy = Policy.Define("Example Policy", "This is an example policy") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .ResideInNamespace("NetArchTest.SampleLibrary.Presentation") .ShouldNot() .HaveDependencyOn("NetArchTest.SampleLibrary.Data"), "Enforcing layered architecture", "Controllers should not directly reference repositories") .Add(t => t.That() .ImplementInterface(typeof(IWidgetService)) .Should() .BeSealed(), "Service class sealing", "All service implementations must be sealed") .Add(t => t.That() .AreInterfaces() .Should() .HaveNameStartingWith("I"), "Interface naming", "Interface names should start with 'I'"); var results = architecturePolicy.Evaluate(); Console.WriteLine($"Policy: {results.Name}"); Console.WriteLine($"Description: {results.Description}"); Console.WriteLine($"Has Violations: {results.HasViolations}"); Console.WriteLine(); foreach (var result in results.Results) { Console.WriteLine($"Rule: {result.Name}"); Console.WriteLine($" Description: {result.Description}"); Console.WriteLine($" Success: {result.IsSuccessful}"); if (!result.IsSuccessful) { Console.WriteLine($" Failing types:"); foreach (var type in result.FailingTypes) { Console.WriteLine($" - {type.FullName}"); } } } ``` -------------------------------- ### DoNotHaveNameStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Selects types whose names do not start with specified text. ```APIDOC ## DoNotHaveNameStartingWith(params string[]) ### Description Selects types whose names do not start with specified text. ### Method `Predicates.DoNotHaveNameStartingWith` ### Parameters #### Path Parameters - **start** (string[]) - Required - One or more name prefixes to exclude ### Request Example ```csharp types.That().DoNotHaveNameStartingWith("Test", "Mock").Should().NotBeAbstract().GetResult(); ``` ``` -------------------------------- ### HaveNameStartingWith with StringComparison Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts type names start with text using specified comparison rules. Allows for custom case sensitivity or culture-specific comparisons. ```csharp public ConditionList HaveNameStartingWith(string start, StringComparison comparer) ``` -------------------------------- ### AND/OR Grouping with Fluent API in C# Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/fluent-chaining.md This example shows the actual fluent API usage for AND/OR grouping, chaining predicates and conditions to define architectural rules. ```csharp var result = Types.InCurrentDomain() .That() .ResideInNamespace("MyApp.Data") .And() .AreClasses() .And() .ImplementInterface(typeof(IRepository)) .Or() .AreAbstract() .Should() .BeSealed() .ShouldNot() .HaveDependencyOn("MyApp.Presentation") .GetResult(); ``` -------------------------------- ### ImplementInterface Condition Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that types implement a specific interface. This example demonstrates how to check if types ending with 'Service' implement the IService interface. ```csharp Types.InCurrentDomain() .That().AreClasses().And().HaveNameEndingWith("Service") .Should().ImplementInterface(typeof(IService)) .GetResult(); ``` -------------------------------- ### Basic Test Assertion Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Perform a basic test assertion to check if all classes are public. The example demonstrates how to use GetResult() and then assert the IsSuccessful property, providing a count of failing types in the assertion message. ```csharp var result = Types.InCurrentDomain() .That().AreClasses() .Should().BePublic() .GetResult(); Assert.True(result.IsSuccessful, $"Expected all classes to be public, but {result.FailingTypes.Count} were not."); ``` -------------------------------- ### Load Types from an Assembly Source: https://github.com/benmorris/netarchtest/blob/master/README.md Initialize the type selection process by loading all types from a specific assembly. This is the starting point for defining architectural rules. ```csharp var types = Types.InAssembly(typeof(MyClass).Assembly); ``` -------------------------------- ### Basic Rule Structure Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Demonstrates the fundamental structure for defining and executing a NetArchTest rule. Use this as a starting point for creating your own rules. The result can be checked for success, and failing type names can be iterated. ```csharp var result = Types.InCurrentDomain() .That() [predicate filters] .Should() [condition assertions] .GetResult(); if (!result.IsSuccessful) { foreach (var failingTypeName in result.FailingTypeNames) { Console.WriteLine(failingTypeName); } } ``` -------------------------------- ### Implement Custom Rules with ICustomRule Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Define custom architectural rules by implementing the ICustomRule interface. Each rule must provide a MeetsRule method that returns true if the type meets the rule, and false otherwise. Examples include repository naming conventions, disallowing public fields, and enforcing single responsibility for service classes. ```csharp using Mono.Cecil; using NetArchTest.Rules; public class RepositoryNamingRule : ICustomRule { public bool MeetsRule(TypeDefinition type) { // Rule: Types with IRepository interface must end with "Repository" var implementsIRepository = type.Interfaces .Any(i => i.InterfaceType.Name == "IRepository"); if (!implementsIRepository) return true; // Rule only applies to IRepository implementations return type.Name.EndsWith("Repository", System.StringComparison.InvariantCultureIgnoreCase); } } public class NoPublicFieldsRule : ICustomRule { public bool MeetsRule(TypeDefinition type) { // Rule: Types should not have public fields return !type.Fields.Any(f => f.IsPublic); } } public class SingleResponsibilityRule : ICustomRule { public bool MeetsRule(TypeDefinition type) { // Rule: Classes with Service in their name should have <= 3 public methods if (!type.Name.EndsWith("Service")) return true; var publicMethodCount = type.Methods .Count(m => m.IsPublic && !m.IsSpecialName); return publicMethodCount <= 3; } } ``` -------------------------------- ### Complex Rule Chaining in C# Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/fluent-chaining.md This example demonstrates a complex rule using fluent chaining to find classes in a specific namespace that meet multiple criteria, including interface implementation, sealing, and abstract status, while also asserting dependencies. ```csharp // Find all classes in Data namespace that either: // 1. Implement IRepository AND are sealed // 2. Are abstract // And assert they don't depend on presentation layer var result = Types.InCurrentDomain() .That() .ResideInNamespace("MyApp.Data") .And() .AreClasses() .Should() .HaveDependencyOn("MyApp.Business") // AND: must depend on business .And() ( (ImplementInterface(typeof(IRepository)) && BeSealed()) // OR group 1 || BeAbstract() // OR group 2 ) .ShouldNot() .HaveDependencyOn("MyApp.Presentation") .GetResult(); ``` -------------------------------- ### Get Result Information Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Retrieve test results and analyze successful or failing types. ```csharp .GetResult() // TestResult with IsSuccessful and FailingTypes .GetTypes() // IEnumerable .Count() // int count of matching types ``` -------------------------------- ### Find Types by Name Matching Pattern Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Use this snippet to find types whose names match a given regular expression pattern. This example specifically looks for interfaces. ```csharp // Find types with names matching pattern var result = Types.InCurrentDomain() .That() .HaveNameMatching(@"^I\w+$") // Interfaces (start with I) .Should() .AreInterfaces() .GetResult(); ``` -------------------------------- ### Implement a Custom Rule with NetArchTest Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Example of a custom rule that checks if classes in the 'MyApp.Models' namespace inherit from 'EntityBase'. It handles abstract classes, interfaces, and namespace checks. ```csharp public class EntityBaseRule : ICustomRule { public bool MeetsRule(TypeDefinition type) { // Rule: Classes in the Models namespace must inherit from EntityBase // Exceptions: Abstract classes and interfaces if (type.IsInterface || type.IsAbstract) return true; // Rule doesn't apply if (!type.Namespace?.StartsWith("MyApp.Models") ?? false) return true; // Rule doesn't apply var hasEntityBaseParent = type.BaseType != null && (type.BaseType.Name == "EntityBase" || type.BaseType.FullName == "MyApp.Common.EntityBase"); return hasEntityBaseParent; } } ``` -------------------------------- ### Evaluate Rule and Get Result Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/fluent-chaining.md Use GetResult() to evaluate the constructed rule and obtain a TestResult object. Check the result for success status and failing types. ```csharp var result = Types.InCurrentDomain() .That() .ArePublic() .Should() .HaveNameStartingWith("I") .GetResult(); if (!result.IsSuccessful) { Console.WriteLine($"{result.FailingTypes.Count} public types don't start with 'I'"); } ``` -------------------------------- ### Find Types by Namespace Matching Pattern Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Use this snippet to find types residing in namespaces that match a given regular expression pattern. This example targets namespaces ending with '.Data'. ```csharp // Find types in namespaces matching pattern var result = Types.InCurrentDomain() .That() .ResideInNamespaceMatching(@".*\.Data$") // Ends with .Data .Should() .HaveDependencyOn("EntityFramework") .GetResult(); ``` -------------------------------- ### Filter Types by Interface Implementation Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Use this predicate to select types that implement a specific interface. The interface type to match is provided as a parameter. This example also chains another predicate to check if the type is sealed. ```csharp types.That().ImplementInterface(typeof(IDisposable)).Should().BeSealed().GetResult(); ``` -------------------------------- ### Entry Points for Selecting Types Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/INDEX.md Demonstrates various methods to specify the initial set of types to be tested. ```csharp Types.InCurrentDomain() Types.InAssembly(assembly) Types.InNamespace(name) Types.FromPath(path) Types.FromFile(filename) Types.InAssemblies(assemblies) ``` -------------------------------- ### Define a Custom Rule: ServiceCountRule Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md This example shows a concrete implementation of ICustomRule. It checks if a type ending with 'Service' has a public method count within a specified limit. This rule is applied directly in code. ```csharp public class ServiceCountRule : ICustomRule { private const int MaxPublicMethods = 3; public bool MeetsRule(TypeDefinition type) { if (!type.Name.EndsWith("Service")) return true; var publicMethodCount = type.Methods .Count(m => m.IsPublic && !m.IsSpecialName); return publicMethodCount <= MaxPublicMethods; } } ``` -------------------------------- ### ResideInNamespaceStartingWith Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Selects types in namespaces that begin with a specified string. ```APIDOC ## ResideInNamespaceStartingWith(string name) ### Description Selects types in namespaces starting with specified text. ### Method `ResideInNamespaceStartingWith` ### Parameters #### Path Parameters - **name** (string) - Required - Namespace prefix ### Request Example ```csharp types.That().ResideInNamespaceStartingWith("MyApp.").GetTypes(); ``` ### Returns `PredicateList` — Updated predicates for chaining. ``` -------------------------------- ### Filtering Test Results Example Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Filter out test results that are not related to testing. This example retrieves failing type names for classes that should inherit from EntityBase, then uses LINQ to exclude names containing 'Test' before reporting the remaining ones. ```csharp var result = Types.InCurrentDomain() .That().AreClasses() .Should().Inherit(typeof(EntityBase)) .GetResult(); var failingClassNames = result.FailingTypeNames .Where(t => !t.Contains("Test")) .ToList(); if (failingClassNames.Any()) { Console.WriteLine("Non-test classes not inheriting from EntityBase:"); foreach (var name in failingClassNames) { Console.WriteLine($" - {name}"); } } ``` -------------------------------- ### Policy Static and Instance Methods Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/types.md Static and instance methods for creating and defining reusable architectural policies. ```APIDOC ## Policy Located in `NetArchTest.Rules.Policies` A sealed class for creating reusable architectural policies. **Static Methods:** - `Define(string, string)` → Policy **Instance Methods:** - `For(Func)` → PolicyDefinition - `For(Types)` → PolicyDefinition ``` -------------------------------- ### Select Types by Namespace Prefix Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Use ResideInNamespaceStartingWith to select types in namespaces that begin with a specified string. ```csharp types.That().ResideInNamespaceStartingWith("MyApp.").GetTypes(); ``` -------------------------------- ### BeSealed() Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that types are marked as sealed. This method is used for chaining conditions and includes an example. ```APIDOC ## BeSealed() ### Description Asserts that types are marked as sealed. ### Method Signature ```csharp public ConditionList BeSealed() ``` ### Returns `ConditionList` — Updated conditions for chaining. ### Example ```csharp Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Services") .Should().BeSealed() .GetResult(); ``` ``` -------------------------------- ### Define and Evaluate Architecture Policies with Custom Rules Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Create reusable architecture policies that incorporate custom rules. This approach allows for a more structured and declarative way to define and evaluate multiple architectural constraints, including custom ones, and provides detailed results for failed rules. ```csharp var architecturePolicy = Policy.Define("Custom Rules Policy", "Enforces organization-specific architectural rules") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .ImplementInterface(typeof(IRepository)) .Should() .MeetCustomRule(new RepositoryNamingRule()), "Repository naming convention", "All IRepository implementations must end with 'Repository'") .Add(t => t.That() .AreClasses() .Should() .MeetCustomRule(new NoPublicFieldsRule()), "No public fields", "Classes should not expose public fields") .Add(t => t.That() .HaveNameEndingWith("Service") .Should() .MeetCustomRule(new SingleResponsibilityRule()), "Single responsibility", "Service classes should have limited public methods"); var results = architecturePolicy.Evaluate(); foreach (var rule in results.Results.Where(r => !r.IsSuccessful)) { Console.WriteLine($"FAILED: {rule.Name}"); Console.WriteLine($" {rule.Description}"); foreach (var failingType in rule.FailingTypes) { Console.WriteLine($" - {failingType.FullName}"); } } ``` -------------------------------- ### MeetCustomRule Method Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Asserts that types meet a custom rule implementation. Use this to define and apply your own specific architectural constraints. ```csharp public ConditionList MeetCustomRule(ICustomRule rule) ``` -------------------------------- ### Retrieve Matching Types Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/fluent-chaining.md Use GetTypes() to get a collection of all types that satisfy the defined conditions. This method returns an IEnumerable. ```csharp var sealedTypes = Types.InCurrentDomain() .That() .AreClasses() .Should() .BeSealed() .GetTypes(); ``` -------------------------------- ### Assert Type is Sealed Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/conditions.md Use this condition to assert that a type is marked as sealed. This example demonstrates asserting that types residing in a specific namespace are sealed. ```csharp public ConditionList BeSealed() ``` ```csharp Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Services") .Should().BeSealed() .GetResult(); ``` -------------------------------- ### FromPath(string, IEnumerable?) Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Creates a list of all types found in assembly files (.dll) within a specified directory. It also allows for specifying additional directories to search for referenced assemblies. ```APIDOC ## FromPath(string, IEnumerable?) ### Description Creates a list of all types found in assembly files (.dll) in a directory. ### Method `public static Types FromPath(string path, IEnumerable searchDirectories = null)` ### Parameters #### Path Parameters - **path** (`string`) - Required - The relative path to search for .dll files - **searchDirectories** (`IEnumerable?`) - Optional - Optional directories to search when resolving referenced assemblies ### Returns `Types` — A Types instance containing all types from all .dll files in the directory. ### Throws - `ArgumentNullException` — if path is null or empty - `DirectoryNotFoundException` — if the path does not exist ### Example ```csharp var types = Types.FromPath("bin/Release"); var publicTypes = types.That().ArePublic().GetTypes(); ``` ``` -------------------------------- ### Apply Condition: Be Sealed Source: https://github.com/benmorris/netarchtest/blob/master/README.md Apply a condition to the filtered types, requiring them to be sealed. This is an example of using the 'Should()' method to enforce a specific type characteristic. ```csharp types.That().ResideInNamespace(“MyProject.Data”).Should().BeSealed(); ``` -------------------------------- ### API Reference - Fluent Chaining Classes Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/README.md Documentation for fluent chaining classes, explaining how to construct complex rule definitions using AND/OR logic. ```APIDOC ## API Reference - Fluent Chaining Classes ### Description Documentation for fluent chaining classes, explaining how to construct complex rule definitions using AND/OR logic. ### Classes - **PredicateList**: Provides `Should()`, `ShouldNot()`, `And()`, `Or()`, and `GetTypes()` methods for building predicate chains. - **ConditionList**: Provides `GetResult()`, `Count()`, `GetTypes()`, `And()`, and `Or()` methods for evaluating condition chains. ### Logic - **AND/OR logic**: Explains how to combine multiple predicates or conditions using logical AND and OR operators. ``` -------------------------------- ### FromFile(string) Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Creates a list of types from an assembly file specified by its filename. This method assumes the assembly file is located in the same directory as the executing assembly. ```APIDOC ## FromFile(string) ### Description Creates a list of types from an assembly file by filename (assumes same directory as executing assembly). ### Method `public static Types FromFile(string filename)` ### Parameters #### Path Parameters - **filename** (`string`) - Required - The assembly filename (e.g., "MyAssembly.dll") ### Returns `Types` — A Types instance containing all types from the specified file. ### Throws - `ArgumentNullException` — if filename is null or empty - `FileNotFoundException` — if the file does not exist ### Example ```csharp var types = Types.FromFile("NetArchTest.SampleLibrary.dll"); ``` ``` -------------------------------- ### Define a New Policy Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/policies.md Use this static factory method to create a new named policy definition. Provide a simple name and a detailed description of the policy's purpose. ```csharp var policy = Policy.Define("Layered Architecture", "Enforces separation between presentation, business logic, and data layers"); ``` -------------------------------- ### Types Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/types.md The entry point for architectural testing. It provides static factory methods to load types and fluent API methods to apply rules. ```APIDOC ## Types ### Description A sealed class serving as the entry point for architectural testing. Provides static factory methods to load types and fluent API methods to apply rules. ### Static Factory Methods - `InCurrentDomain()` → Types - `InAssembly(Assembly, IEnumerable?)` → Types - `InAssemblies(IEnumerable, IEnumerable?)` → Types - `InNamespace(string)` → Types - `FromFile(string)` → Types - `FromPath(string, IEnumerable?)` → Types ### Fluent API Methods - `That()` → Predicates - `Should()` → Conditions - `ShouldNot()` → Conditions - `GetTypes()` → IEnumerable ``` -------------------------------- ### Loading Types Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Shows various methods for loading types into NetArchTest for analysis. Choose the method that best suits your needs, whether it's loading from the current domain, a specific assembly, a namespace, a directory, or a single file. ```csharp Types.InCurrentDomain() // All non-system assemblies ``` ```csharp Types.InAssembly(assembly) // Specific assembly ``` ```csharp Types.InNamespace("MyApp") // All types in namespace ``` ```csharp Types.FromPath("bin/Release") // All DLLs in directory ``` ```csharp Types.FromFile("Assembly.dll") // Single DLL file ``` -------------------------------- ### Using Custom Rule as a Predicate Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Demonstrates how to integrate a custom rule into the predicate chain to filter types. Ensure your custom rule class is instantiated before use. ```csharp var myRule = new MyCustomRule(); var types = Types.InCurrentDomain() .That() .MeetCustomRule(myRule) .Should() .BeSealed() .GetResult(); ``` -------------------------------- ### InNamespace(string) Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Creates a list of all types residing within a specified namespace across all loaded assemblies. The namespace matching is case-insensitive. ```APIDOC ## InNamespace(string) ### Description Creates a list of all types in a particular namespace from any loaded assembly. ### Method `public static Types InNamespace(string name)` ### Parameters #### Path Parameters - **name** (`string`) - Required - The namespace to match (case insensitive) ### Returns `Types` — A Types instance containing all types in the specified namespace. ### Throws - `ArgumentNullException` — if name is null or empty ### Example ```csharp var dataTypes = Types.InNamespace("MyApp.Data"); var repositories = dataTypes.That().HaveNameEndingWith("Repository").GetTypes(); ``` ``` -------------------------------- ### Define and Add Rules to a Policy Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/policies.md Use this snippet to define a new policy, specify the types to evaluate, and add multiple rules with names and descriptions. This is useful for setting up comprehensive architectural checks. ```csharp var policy = Policy.Define("Architecture", "Layered architecture rules") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .ResideInNamespace("MyApp.Presentation") .ShouldNot() .HaveDependencyOn("MyApp.Data"), "No direct data access from UI", "The presentation layer should depend on business logic, not data layer") .Add(t => t.That() .AreInterfaces() .Should() .HaveNameStartingWith("I"), "Interface naming", "All interfaces must start with 'I'"); ``` -------------------------------- ### Get failing types as names Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Obtain a list of fully qualified type names that failed the test using the FailingTypeNames property. This is a safer approach as it avoids loading the types, thus preventing potential dependency loading errors. ```csharp var result = Types.InCurrentDomain() .That().ResideInNamespace("MyApp") .Should().ArePublic() .GetResult(); foreach (var name in result.FailingTypeNames) { Console.WriteLine($"Type not public: {name}"); } ``` -------------------------------- ### Get failing types as Type objects Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/test-results.md Retrieve a list of Type objects that failed the test using the FailingTypes property. Be aware that this loads the types, which might cause dependency loading errors. Prefer FailingTypeNames if only names are needed. ```csharp var result = Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Data") .Should().BeSealed() .GetResult(); foreach (var failingType in result.FailingTypes) { Console.WriteLine($"{failingType.Name} is not sealed"); } ``` -------------------------------- ### Check Class Dependencies and Namespace Source: https://github.com/benmorris/netarchtest/blob/master/README.md Verify that classes in a specific namespace do not depend on another specified namespace. This is useful for enforcing layered architecture. ```csharp // Classes in the presentation should not directly reference repositories var result = Types.InCurrentDomain() .That() .ResideInNamespace("NetArchTest.SampleLibrary.Presentation") .ShouldNot() .HaveDependencyOn("NetArchTest.SampleLibrary.Data") .GetResult() .IsSuccessful; ``` -------------------------------- ### Result Evaluation Methods Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/INDEX.md Demonstrates the three methods available for evaluating the results of the architectural tests: GetResult(), GetTypes(), and Count(). ```csharp .GetResult() .GetTypes() .Count() ``` -------------------------------- ### Implement and Use Custom Rule Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Create a custom rule by implementing the ICustomRule interface to define specific criteria for type validation. This allows for flexible and complex architectural checks. ```csharp public class MyRule : ICustomRule { public bool MeetsRule(TypeDefinition type) { // Return true if type meets the rule return !type.Name.Contains("Test"); } } var rule = new MyRule(); Types.InCurrentDomain() .That() .AreClasses() .Should() .MeetCustomRule(rule) .GetResult(); ``` -------------------------------- ### Define a Policy with Rules Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Define a policy using a fluent API, specifying the types to evaluate and the rules to add. Optional names and descriptions can be provided for rules. ```csharp Policy.Define("Policy Name", "Policy Description") .For(() => Types.InCurrentDomain()) .Add(rule1, "Rule 1 Name", "Rule 1 Description") .Add(rule2, "Rule 2 Name", "Rule 2 Description") .Evaluate() ``` -------------------------------- ### Policy.Define Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/policies.md Creates a new named policy definition with a name and description. ```APIDOC ## Policy.Define(string name, string description) ### Description Creates a new named policy definition. ### Method Static Factory Method ### Signature `public static Policy Define(string name, string description)` ### Parameters #### Path Parameters - **name** (string) - Required - Simple name of the policy (e.g., "Layered Architecture") - **description** (string) - Required - Detailed description of the policy's purpose ### Returns `PolicyDefinition` — A policy builder for adding rules and types. ### Example ```csharp var policy = Policy.Define("Layered Architecture", "Enforces separation between presentation, business logic, and data layers"); ``` ``` -------------------------------- ### Use a Custom Rule in Tests Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Instantiate your custom rule and use it with the fluent API to apply architectural checks. This demonstrates how to integrate custom logic into the testing framework. ```csharp var rule = new ServiceCountRule(); var result = Types.InCurrentDomain() .That() .AreClasses() .Should() .MeetCustomRule(rule) .GetResult(); ``` -------------------------------- ### InAssembly(Assembly, IEnumerable?) Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Creates a list of types from a single specified assembly. Optionally, you can provide directories to search for referenced assemblies. ```APIDOC ## InAssembly(Assembly, IEnumerable?) ### Description Creates a list of types from a single assembly. ### Method `public static Types InAssembly(Assembly assembly, IEnumerable searchDirectories = null)` ### Parameters #### Path Parameters - **assembly** (`Assembly`) - Required - The assembly to load types from - **searchDirectories** (`IEnumerable?`) - Optional - Optional directories to search when resolving referenced assemblies ### Returns `Types` — A Types instance containing all types from the specified assembly. ### Throws - `ArgumentNullException` — if assembly is null ### Example ```csharp var assembly = typeof(MyClass).Assembly; var types = Types.InAssembly(assembly); var interfaces = types.That().AreInterfaces().GetTypes(); ``` ``` -------------------------------- ### Implement Custom Rule with MeetCustomRule Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Use MeetCustomRule to select types that satisfy a custom rule implementation. Ensure your custom rule implements the ICustomRule interface. ```csharp public PredicateList MeetCustomRule(ICustomRule rule) { // ... implementation details } ``` ```csharp var customRule = new MyCustomRule(); types.That().MeetCustomRule(customRule).Should().BeSealed().GetResult(); ``` -------------------------------- ### Naming Convention: Services End with Service Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Checks that all classes within the MyApp.Services namespace end with the suffix 'Service'. This convention aids in identifying service classes. ```csharp // Services end with Service Types.InCurrentDomain() .That().ResideInNamespace("MyApp.Services") .Should().HaveNameEndingWith("Service") .GetResult(); ``` -------------------------------- ### Load System Types Explicitly Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md System types are excluded by default. Load them directly by specifying the assembly. ```csharp // System types are excluded by default var allTypes = Types.InCurrentDomain(); // To analyze a specific assembly directly: var systemTypes = Types.InAssembly(typeof(object).Assembly); ``` -------------------------------- ### Implement ICustomRule Interface Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/configuration.md Custom rules must implement the ICustomRule interface, which includes a single MeetsRule method. Configuration logic is placed within this method. ```csharp public interface ICustomRule { bool MeetsRule(TypeDefinition type); } ``` -------------------------------- ### Filter types by name prefix with custom comparer Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Use HaveNameStartingWith with a StringComparison parameter to specify custom rules for matching name prefixes, such as case-insensitivity. ```csharp types.That().HaveNameStartingWith("i", StringComparison.OrdinalIgnoreCase).AreInterfaces().GetTypes(); ``` -------------------------------- ### Type Dependencies - Policy Class Hierarchy Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/types.md Shows the hierarchy and methods involved in defining and evaluating policies within the NetArchTest.Rules library. ```text Policy.Define() → Policy → For() → PolicyDefinition ↓ Add() / Evaluate() ↓ PolicyResults ↓ PolicyResult[] ``` -------------------------------- ### API Reference - ICustomRule Interface Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/README.md Documentation for the ICustomRule interface, enabling the creation and integration of custom architectural rules. ```APIDOC ## API Reference - ICustomRule Interface ### Description Documentation for the ICustomRule interface, enabling the creation and integration of custom architectural rules. ### Interface - **ICustomRule**: Requires implementation of the `MeetRule(TypeDefinition)` method. ### Usage - Implement custom logic within the `MeetRule` method. - Use custom rules as predicates and conditions. - Integrate custom rules into policies for comprehensive architectural enforcement. ``` -------------------------------- ### Load Types from a Specific Namespace Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Creates a list of all types residing within a given namespace across all loaded assemblies. The namespace matching is case-insensitive. ```csharp var dataTypes = Types.InNamespace("MyApp.Data"); var repositories = dataTypes.That().HaveNameEndingWith("Repository").GetTypes(); ``` -------------------------------- ### Filter types by name prefix Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/predicates.md Use HaveNameStartingWith to select types whose names begin with one or more specified prefixes. This method is case-sensitive by default. ```csharp types.That().HaveNameStartingWith("I").AreInterfaces().GetTypes(); ``` -------------------------------- ### Define and Evaluate Architectural Policy Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/quick-reference.md Define a reusable architectural policy with specific rules and evaluate it against types in the current domain. Use this to enforce coding standards and architectural patterns. ```csharp var policy = Policy.Define("My Policy", "Description") .For(() => Types.InCurrentDomain()) .Add(t => t.That() .ResideInNamespace("MyApp.Data") .Should() .Inherit(typeof(EntityBase)), "Entity inheritance", "All data entities must inherit from EntityBase") .Add(t => t.That() .AreInterfaces() .Should() .HaveNameStartingWith("I"), "Interface naming", "All interfaces must start with 'I'"); var results = policy.Evaluate(); if (results.HasViolations) { foreach (var result in results.Results.Where(r => !r.IsSuccessful)) { Console.WriteLine($"FAILED: {result.Name}"); Console.WriteLine($" {result.Description}"); foreach (var type in result.FailingTypes) { Console.WriteLine($" - {type.FullName}"); } } } ``` -------------------------------- ### Usage as Predicate Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Demonstrates how to use a custom rule as a predicate to filter types within a query. ```APIDOC ## Usage as Predicate Custom rules can be used in `Predicates` to filter types: ```csharp var myRule = new MyCustomRule(); var types = Types.InCurrentDomain() .That() .MeetCustomRule(myRule) .Should() .BeSealed() .GetResult(); ``` ``` -------------------------------- ### Apply Custom Rules in Unit Tests Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Integrate custom rules into your unit tests using the NetArchTest library. Instantiate your custom rule and use the MeetCustomRule condition within your architecture tests to validate specific architectural constraints. ```csharp using Xunit; using NetArchTest.Rules; public class ArchitectureTests { [Fact] public void Repositories_Should_Follow_Naming_Convention() { var rule = new RepositoryNamingRule(); var result = Types.InCurrentDomain() .That() .ImplementInterface(typeof(IRepository)) .Should() .MeetCustomRule(rule) .GetResult(); Assert.True(result.IsSuccessful, string.Format("Repository implementations must end with 'Repository'. " + "Failed types: {0}", string.Join(", ", result.FailingTypeNames))); } [Fact] public void Classes_Should_Not_Have_Public_Fields() { var rule = new NoPublicFieldsRule(); var result = Types.InCurrentDomain() .That() .AreClasses() .Should() .MeetCustomRule(rule) .GetResult(); Assert.True(result.IsSuccessful); } [Fact] public void Services_Should_Have_Single_Responsibility() { var rule = new SingleResponsibilityRule(); var result = Types.InCurrentDomain() .That() .AreClasses() .Should() .MeetCustomRule(rule) .GetResult(); Assert.True(result.IsSuccessful); } } ``` -------------------------------- ### Load Types from an Assembly File Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Loads types from an assembly file specified by its filename. Assumes the file is in the same directory as the executing assembly. Throws `FileNotFoundException` if the file does not exist. ```csharp var types = Types.FromFile("NetArchTest.SampleLibrary.dll"); ``` -------------------------------- ### ICustomRule Interface Signature Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/custom-rules.md Defines the contract for custom architectural rules. Implement this interface to create your own rules. ```csharp public interface ICustomRule ``` -------------------------------- ### Load Types from Assemblies in a Directory Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/types.md Loads types from all .dll files found within a specified directory. Optionally, provide search directories for resolving referenced assemblies. Throws `DirectoryNotFoundException` if the path does not exist. ```csharp var types = Types.FromPath("bin/Release"); var publicTypes = types.That().ArePublic().GetTypes(); ``` -------------------------------- ### Chain Predicates with AND Logic using And() Source: https://github.com/benmorris/netarchtest/blob/master/_autodocs/api-reference/fluent-chaining.md Use And() to chain additional predicates with AND logic. AND operations have higher priority and are evaluated before OR operations. ```csharp var result = Types.InCurrentDomain() .That() .AreClasses() .And() // Additional AND predicate .HaveNameEndingWith("Service") .Should() .BeSealed() .GetResult(); ```