Free, MIT-licensed compile-time architecture rule enforcement for .NET. No commercial license, no separate desktop tool, no CI-only step — violations show up as build warnings/errors the moment they're introduced, right in your IDE.
Tools like NDepend are excellent for deep codebase analysis but require a paid commercial license. If all you need is "the UI layer must never reference the data-access layer directly," you shouldn't need a separate license and a separate analysis pass for that. AutoArchitecture is a Roslyn source generator: declare your rules once as assembly attributes, and every build enforces them for free.
[assembly: AutoArchitecture.ForbidDependency("MyApp.UI", "MyApp.DataAccess",
Because = "UI must go through the service layer, not the repositories directly")]The moment any type in MyApp.UI (or a sub-namespace like MyApp.UI.Views) references a
type in MyApp.DataAccess (or a sub-namespace), you get:
warning AA001: 'OrderController' in namespace 'MyApp.UI' references 'OrderRepository' in
namespace 'MyApp.DataAccess', which is forbidden by
[assembly: ForbidDependency("MyApp.UI", "MyApp.DataAccess")]
(UI must go through the service layer, not the repositories directly)
AutoArchitecture can also detect namespace cycles — the capability NDepend is best known for — with an opt-in assembly attribute:
[assembly: AutoArchitecture.DetectCircularDependencies]dotnet add package AutoArchitectureAdd one [assembly: ForbidDependency(from, to)] attribute per rule anywhere in your
project (e.g. in AssemblyInfo.cs or alongside your Program.cs):
[assembly: AutoArchitecture.ForbidDependency("MyApp.Presentation", "MyApp.Infrastructure")]
[assembly: AutoArchitecture.ForbidDependency("MyApp.Domain", "MyApp.Infrastructure")]- Namespace matching includes sub-namespaces: a rule for
MyApp.DataAccessalso coversMyApp.DataAccess.Sql,MyApp.DataAccess.Migrations, etc. - Rules only match on exact/dot-boundary prefixes, so
MyApp.DataAccessdoes not accidentally match an unrelatedMyApp.DataAccessLegacynamespace. - The
Becausenamed argument is optional and is included verbatim in the diagnostic message — handy for explaining why the rule exists to whoever hits it next. - AA001 is a
Warningby default. Promote it to a build-breaking error per-project with a standard.editorconfigseverity override:dotnet_diagnostic.AA001.severity = error
Add [assembly: DetectCircularDependencies] when you want AutoArchitecture to analyze the
entire compilation's namespace graph and flag actual dependency cycles:
[assembly: AutoArchitecture.DetectCircularDependencies]
namespace MyApp.A
{
public class AType
{
private readonly B.BType _dependency = new B.BType();
}
}
namespace MyApp.B
{
public class BType
{
private readonly C.CType _dependency = new C.CType();
}
}
namespace MyApp.C
{
public class CType
{
private readonly A.AType _dependency = new A.AType();
}
}That produces warnings on the participating references, for example:
warning AA002: 'AType' in namespace 'MyApp.A' references 'BType' in namespace 'MyApp.B',
creating a circular dependency: MyApp.A -> MyApp.B -> MyApp.C -> MyApp.A
- Circular dependency detection is opt-in because it analyzes the full namespace dependency graph for the current compilation.
- AA002 is a
Warningby default and can be promoted/demoted with standard Roslyn severity configuration:dotnet_diagnostic.AA002.severity = error - AA001 and AA002 can be enabled together: explicit
ForbidDependencyrules still catch disallowed directions even when those references are also part of a cycle.
- MIT licensed, forever. No commercial tier, no per-seat fees, no desktop app to buy.
- Zero runtime cost — this is a source generator/analyzer; nothing ships in your compiled output.
- IDE-first feedback — violations appear as squiggles while you type, not just in a nightly CI report.
- Simple, declarative rules — no XML rule files or query languages to learn.
- Allow-list exceptions for specific types within an otherwise-forbidden namespace pair are planned for a future release, to support gradual migrations.
| Package | Downloads | Description |
|---|---|---|
| AutoWire | Compile-time dependency injection auto-registration for | |
| AutoMap.Generator | Compile-time object mapping for | |
| AutoQuery.Generator | Compile-time query composition for IQueryable using Roslyn incremental source generators | |
| AutoHttpClient.Generator | Compile-time typed HTTP client generation for | |
| AutoDispatch.Generator | Compile-time CQRS dispatcher for | |
| AutoLog.Generator | Compile-time high-performance logging for | |
| AutoValidate.Generator | Compile-time FluentValidation wiring for |
I'm the author of AutoArchitecture and a suite of compile-time source generators (AutoWire, AutoMap.Generator) and 28+ Polly v8 resilience packages. I'm available for consulting on Polly v8 resilience, Azure cloud architecture, and clean .NET design.
→ solidqualitysolutions.com · LinkedIn
🌐 Full suite overview: swevo.github.io
| Package | Description |
|---|---|
| FluentPdf | Free, MIT-licensed fluent PDF generation — alternative to QuestPDF's commercial license. |
| AutoBus | Free, MIT-licensed message bus — alternative to MassTransit's commercial license. |
| AutoAssert | Free, MIT-licensed fluent assertions — alternative to FluentAssertions' commercial license. |
| EFCore.BulkOperations | Free, MIT-licensed bulk insert/update/delete for EF Core. |
| AutoWire | Compile-time DI auto-registration — [Scoped]/[Singleton]/[Transient] generates IServiceCollection registration code. |
| AutoMap.Generator | Compile-time object mapping — [Map(typeof(Dto))] generates ToDto() extension methods. |
| AutoDispatch.Generator | Compile-time CQRS dispatcher — free alternative to MediatR's commercial license. |
| PollyAnalyzers | Free Roslyn analyzers for async/resilience anti-patterns — blocking calls, async void, fire-and-forget tasks, swallowed exceptions. |
| PollyAction | Free retry/backoff GitHub Action — wrap any CI step with exponential-backoff retries. |
MIT © Justin Bannister