AdvGenFlow.SourceGen 1.0.0

dotnet add package AdvGenFlow.SourceGen --version 1.0.0
                    
NuGet\Install-Package AdvGenFlow.SourceGen -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AdvGenFlow.SourceGen" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AdvGenFlow.SourceGen" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AdvGenFlow.SourceGen" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AdvGenFlow.SourceGen --version 1.0.0
                    
#r "nuget: AdvGenFlow.SourceGen, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AdvGenFlow.SourceGen@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AdvGenFlow.SourceGen&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AdvGenFlow.SourceGen&version=1.0.0
                    
Install as a Cake Tool

AdvGenFlow

A custom MediatR alternative in C# for .NET 9 with request/response, notifications, pipeline behaviors, streaming, reflection-based dispatch, and an opt-in Roslyn source generator for compile-time performance.

Overview

AdvGenFlow provides a lightweight, extensible mediator pattern implementation with two dispatch modes:

  • Reflection-based (Mediator) — uses dynamic dispatch for flexibility
  • Source-generated (GeneratedMediator) — compile-time emitted dispatch using typed switch expressions for maximum performance

Architecture

The solution consists of two packages:

Package Target Description
AdvGenFlow net9.0 Core library with contracts, reflection-based mediator, pipeline builder, and DI extensions
AdvGenFlow.SourceGen netstandard2.0 Incremental Roslyn source generator that emits compile-time GeneratedMediator

Features

  • Request/ResponseIRequest<TResponse> with IRequestHandler<TRequest, TResponse>
  • NotificationsINotification with fan-out to multiple INotificationHandler<TNotification>
  • StreamingIStreamRequest<TResponse> with IStreamRequestHandler<TRequest, TResponse> for IAsyncEnumerable<T>
  • Pipeline BehaviorsIPipelineBehavior<TRequest, TResponse> for cross-cutting concerns (logging, validation, caching, etc.)
  • Dependency Injection — Assembly scanning registration with AddAdvGenFlow() and AddAdvGenFlowBehavior<T>()
  • Source Generator — Opt-in compile-time dispatch generation for zero-reflection performance

Quick Start

Installation

# Core package (required)
dotnet add package AdvGenFlow

# Source generator (optional, for compile-time dispatch)
dotnet add package AdvGenFlow.SourceGen

Basic Usage

1. Define a Request and Handler
using AdvGenFlow;

// Request
public record GetUserQuery(int UserId) : IRequest<User>;

// Handler
public class GetUserHandler : IRequestHandler<GetUserQuery, User>
{
    public Task<User> Handle(GetUserQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult(new User { Id = request.UserId, Name = "John Doe" });
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
}
2. Register with DI
using AdvGenFlow;

var services = new ServiceCollection();

// Reflection-based approach
services.AddAdvGenFlow(typeof(Program).Assembly);

// OR source-generated approach (requires AdvGenFlow.SourceGen package)
// services.AddAdvGenFlowGenerated<GeneratedMediator>(typeof(Program).Assembly);
3. Send Requests
public class UserService(ISender sender)
{
    public async Task<User> GetUserAsync(int userId)
    {
        return await sender.Send(new GetUserQuery(userId));
    }
}

Notifications (Fan-out)

// Notification
public record OrderPlaced(int OrderId) : INotification;

// Multiple handlers
public class EmailNotificationHandler : INotificationHandler<OrderPlaced>
{
    public Task Handle(OrderPlaced notification, CancellationToken cancellationToken)
    {
        // Send email
        return Task.CompletedTask;
    }
}

public class AuditLogHandler : INotificationHandler<OrderPlaced>
{
    public Task Handle(OrderPlaced notification, CancellationToken cancellationToken)
    {
        // Write to audit log
        return Task.CompletedTask;
    }
}

// Publish
await publisher.Publish(new OrderPlaced(orderId));

Streaming

// Stream request
public record LivePriceQuery(string Symbol) : IStreamRequest<decimal>;

// Stream handler
public class LivePriceHandler : IStreamRequestHandler<LivePriceQuery, decimal>
{
    public async IAsyncEnumerable<decimal> Handle(
        LivePriceQuery request,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            yield return await GetCurrentPriceAsync(request.Symbol);
            await Task.Delay(1000, cancellationToken);
        }
    }
}

// Consume stream
await foreach (var price in sender.CreateStream(new LivePriceQuery("AAPL")))
{
    Console.WriteLine($"Current price: {price}");
}

Pipeline Behaviors

// Logging behavior
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;

    public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Handling {Request}", typeof(TRequest).Name);
        var response = await next();
        _logger.LogInformation("Handled {Request}", typeof(TRequest).Name);
        return response;
    }
}

// Register
services.AddAdvGenFlow(typeof(Program).Assembly);
services.AddAdvGenFlowBehavior<LoggingBehavior<,>>();

Project Structure

AdvGenFlow/
├── src/
│   ├── AdvGenFlow/                      # Core library (net9.0)
│   │   ├── Contracts/                   # Interfaces (IRequest, IHandler, etc.)
│   │   ├── Pipeline/                    # PipelineBuilder
│   │   ├── DependencyInjection/         # ServiceCollection extensions
│   │   └── Mediator.cs                  # Reflection-based implementation
│   └── AdvGenFlow.SourceGen/            # Source generator (netstandard2.0)
│       └── MediatorDispatchGenerator.cs # Incremental generator
├── tests/
│   ├── AdvGenFlow.Tests/                # Core tests (xUnit)
│   └── AdvGenFlow.SourceGen.Tests/      # Generator snapshot tests
└── docs/
    └── superpowers/
        ├── plans/                       # Implementation plans
        └── specs/                       # Design specifications

Core Contracts

Interface Purpose
IRequest<TResponse> Marker for request types
IRequestHandler<TRequest, TResponse> Handles requests
INotification Marker for notification types
INotificationHandler<TNotification> Handles notifications
IStreamRequest<TResponse> Marker for streaming requests
IStreamRequestHandler<TRequest, TResponse> Handles streaming requests
IPipelineBehavior<TRequest, TResponse> Cross-cutting pipeline behavior
ISender Send requests and create streams
IPublisher Publish notifications
IMediator Combines ISender and IPublisher

Configuration Options

Reflection-based (Default)

services.AddAdvGenFlow(typeof(Program).Assembly);
services.AddAdvGenFlowBehavior<MyBehavior<,>>();

Source-generated (High Performance)

// Add the source generator package first
services.AddAdvGenFlowGenerated<GeneratedMediator>(typeof(Program).Assembly);

Testing

# Run all tests
dotnet test AdvGenFlow.sln

# Run core tests only
dotnet test tests/AdvGenFlow.Tests/AdvGenFlow.Tests.csproj

# Run source generator tests
dotnet test tests/AdvGenFlow.SourceGen.Tests/AdvGenFlow.SourceGen.Tests.csproj

Tech Stack

  • .NET 9 — Target framework for core library and tests
  • netstandard2.0 — Source generator target for broad compatibility
  • Microsoft.Extensions.DependencyInjection — DI container integration
  • Microsoft.CodeAnalysis.CSharp 4.x — Roslyn source generation
  • xUnit 2.x — Testing framework
  • AwesomeAssertions — Fluent assertions
  • Verify.SourceGenerators — Snapshot testing for generators

License

MIT License — See LICENSE for details.


Built with ❤️ for high-performance, clean architecture applications.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 104 3/23/2026