A collection of .NET libraries for building clean, scalable applications using DDD, CQRS, and Event Sourcing.
Source-only: Aviant is currently consumed by adding it as a git submodule. NuGet packages are planned. See CleanDDDArchitecture for full usage examples.
src/
├── Kernel/ # Core abstractions, behaviours, pipeline
│ ├── Core/ # Entities, Value Objects, Specifications, Timing
│ ├── Application/ # MediatR pipeline behaviours, Commands, Queries
│ └── Infrastructure/ # Cross-cutting DI helpers
├── DDD/ # Domain-Driven Design building blocks
├── EventSourcing/ # Event-sourced aggregates and persistence
├── Identity/ # User identity and JWT authentication
├── Persistence/ # CQRS repositories and Unit of Work
├── Email/ # SMTP email service
└── Jobs/ # Hangfire background job runner
git submodule add https://github.com/panosru/Aviant.git Library/Aviant
git submodule update --init --recursive// In your CrossCutting project
public static IServiceCollection AddMyDomain(this IServiceCollection services)
{
services.AddDbContext<MyDbContext>(...);
services.AddScoped<IMyRepository, MyRepository>();
return services;
}// Command
public sealed record CreateWeatherCommand(string City, double Temperature)
: IRequest<WeatherDto>;
// Handler
public sealed class CreateWeatherCommandHandler
: IRequestHandler<CreateWeatherCommand, WeatherDto>
{
public async Task<WeatherDto> Handle(
CreateWeatherCommand request,
CancellationToken cancellationToken)
{
// ... domain logic
}
}public sealed class AccountAggregate : AggregateRoot<AccountAggregate, AccountId>
{
public string Email { get; private set; } = string.Empty;
public void Register(string email)
{
Apply(new AccountRegisteredEvent(Id, email));
}
protected override void When(IDomainEvent @event)
{
if (@event is AccountRegisteredEvent e)
Email = e.Email;
}
}Aviant registers these behaviours automatically (in order):
PerformanceBehaviour— logs slow requests (>500ms)ValidationBehaviour— runs FluentValidation validatorsUnhandledExceptionBehaviour— logs unhandled exceptionsRetryRequestProcessor— wraps handlers with Polly retry
// AccountService issues JWTs
services.AddAccountDomain(); // includes Identity + JWT issuance
// Other services validate JWTs
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key512),
TokenDecryptionKey = new SymmetricSecurityKey(key256),
};
});Kernel/Core
└── Kernel/Application (adds MediatR)
└── Kernel/Infrastructure (adds DI helpers)
DDD/Core
└── DDD/Application (extends Kernel/Application)
└── DDD/Infrastructure
EventSourcing/Core
└── EventSourcing/Application
└── EventSourcing/Infrastructure
Identity/Core
└── Identity/Application
└── Identity/Infrastructure (uses Kernel + DDD)
Persistence/Core
└── Persistence/Application
└── Persistence/Infrastructure
Email/Application
└── Email/Infrastructure (MailKit/MimeKit)
Jobs/Application
└── Jobs/Infrastructure (Hangfire)
- Add as a git submodule (see above)
- Add
Library/Aviant/Aviant.slnor individual.csprojreferences to your solution - Reference the modules you need from your domain projects
- Register via the
Add*extension methods in yourProgram.csor DI registration class
Pull requests and issue reports are welcome at github.com/panosru/Aviant.