Skip to main content

RA.Utilities.Feature

NuGet version NuGet Downloads Codecov Publish NuGet GitHub license

Deprecated Package

This package is deprecated and has been moved to RA.Utilities.Dispatcher.

The main goal of this package is to help you organize your application's business logic into self-contained "features" or "slices." Instead of having logic for a single operation scattered across multiple layers (e.g., a controller, a service, a repository), all the code for one use case—from the incoming request to the final response—is located together.

This solves a common problem with traditional layered architectures where classes can become bloated and tightly coupled, making the codebase difficult to navigate and maintain.

✨ Key Features and How They Help​

The package provides several key components to achieve this clean architecture:

  1. Custom Mediator (IMediator):
  • Purpose: A lightweight, reflection-free mediator implementation — no external MediatR dependency.
  • Benefit: Strongly-typed generic dispatch for both request/response (Send) and publish/subscribe (Publish) patterns. Send returns the response value directly — errors surface as typed exceptions.
  1. Base Handlers (RequestHandler<TRequest, TResponse>):
  • Purpose: Abstract base classes for your CQRS command and query handlers.
  • Benefit: They remove boilerplate: implement the single abstract HandleAsync method and return values (or throw typed exceptions) directly — no explicit interface plumbing.
  1. Validation Pipeline Behavior (ValidationBehavior<TRequest, TResponse>):
  • Purpose: A pipeline behavior that automatically validates incoming commands and queries before they reach your business logic.
  • Benefit: Uses FluentValidation. If validation fails, it short-circuits by throwing a BadRequestException carrying the structured validation errors. Your handlers only ever deal with valid data.
  1. Notification System (INotification):
  • Purpose: Publish/subscribe eventing — fire-and-forget notifications handled by zero or more subscribers.
  • Benefit: Built-in notification behaviors for logging, metrics, and retry. Each handler is independently wrapped, so one failing handler doesn't prevent others from executing.
  1. Typed Pipeline Context (PipelineContext<T>):
  • Purpose: Pass strongly-typed data through the entire pipeline — no dictionaries, no magic strings, no boxing.
  • Benefit: Behaviors and handlers read/write properties on a user-defined T. Each call gets its own isolated instance. Fully opt-in — existing Send/Publish calls compile unchanged.
  1. Zero-Configuration Handler and Behavior Registration (Auto Registration):
  • Purpose: A source generator shipped in the package discovers all IRequestHandler<,> / IRequestHandler<> / INotificationHandler<> implementations and closed pipeline behaviors, and registers them when AddMediator() is called.
  • Benefit: Plain handlers and closed behaviors need no explicit AddFeature / AddNotification / AddDecoration calls — only validators and generic behaviors still require explicit registration.
  1. Source-Generated Mediator (Generated Mediator):
  • Purpose: The same generator emits the IMediator implementation itself — a per-assembly Mediator with monomorphized Send overloads that inject the known handler and behaviors by concrete type and call them directly (no interface lookups, no GetServices, no casts), plus fast dictionary dispatch above 8 messages and object-based dispatch.
  • Benefit: At equal (scoped) handler lifetimes, benchmarks show the generated mediator 14-18% faster than MediatR with 9-14% fewer allocations in every comparable send shape. Inject IMediator or the concrete Mediator for the fastest path.
  1. Exception-Based Errors (RA.Utilities.Core.Exceptions):
  • Purpose: Handlers communicate failures by throwing typed exceptions (NotFoundException, ConflictException, BadRequestException, ...).
  • Benefit: A single GlobalExceptionHandler at the API layer maps them to consistent HTTP responses — no Result unwrapping at call sites. (The Result<T> monad still exists in RA.Utilities.Core.Results for code that wants it.)
  1. Benchmarked against MediatR (Benchmarks):
  • Purpose: A BenchmarkDotNet harness comparing the generated mediator against MediatR 12.5 at equal scoped lifetimes, scenario for scenario.
  • Benefit: Published numbers for the send shapes — 12-18% faster with 9-14% fewer allocations — plus the harness to reproduce them locally.

🌟 Benefits​

The package has been fully rewritten to avoid reflection; handlers are discovered by a source generator and resolved through strongly-typed generic DI registration instead of dynamic type lookups or runtime assembly scanning.

  • ✅ No runtime reflection
  • ✅ Purely generic and compile-time safe
  • ✅ Zero-config handler registration via the in-package source generator — plain handlers need no registration code
  • ✅ Simplified DI registration via fluent builders (FeatureBuilderExtensions) for behaviors and validators
  • ✅ Custom mediator supports both request/response and publish/subscribe
  • ✅ Multiple notification handlers per notification type
  • ✅ Multiple notification pipeline behaviors (logging, metrics, retry)
  • ✅ Fluent builder style consistent across requests and notifications
  • ✅ Abstract RequestHandler base classes — one HandleAsync override per handler
  • ✅ Exception-based errors — typed exceptions map to HTTP responses via GlobalExceptionHandler
  • ✅ Typed PipelineContext<T> for passing data through the pipeline — no dictionaries

🔧 Design Overview​

NamespacePurpose
AbstractionsCore interfaces: IMediator, IRequest, IRequestHandler, INotification, IPipelineBehavior, INotificationBehavior
HandlersAbstract base classes: RequestHandler<TRequest>, RequestHandler<TRequest, TResponse>
BehaviorsBuilt-in pipeline and notification behaviors: logging, validation, metrics, retry
ExtensionsDI registration extensions: AddMediator(), AddFeature(), AddNotification()
ModelsDelegates: RequestHandlerDelegate, NotificationHandlerDelegate

🛠️ Installation​

You can install the package via the .NET CLI:

dotnet add package RA.Utilities.Feature

Or through the NuGet Package Manager console:

Install-Package RA.Utilities.Feature

🔗 Dependencies​