Class ServiceCollectionExtensions
Extension methods for registering Trellis.Mediator pipeline behaviors.
public static class ServiceCollectionExtensions
- Inheritance
-
ServiceCollectionExtensions
- Inherited Members
Properties
PipelineBehaviors
Gets the ordered array of Trellis Result-aware pipeline behavior types contributed by this
package. Assign this to MediatorOptions.PipelineBehaviors in your AddMediator
call when wiring the AOT-friendly source generator path.
The canonical Trellis pipeline (outermost to innermost) is:
- ExceptionBehavior<TMessage, TResponse> — catches unhandled exceptions and converts to typed failures.
- TracingBehavior<TMessage, TResponse> — emits an OpenTelemetry activity span around the message.
- LoggingBehavior<TMessage, TResponse> — structured logging with duration and outcome.
- AuthorizationBehavior<TMessage, TResponse> — checks static permissions declared by IAuthorize.
- ResourceAuthorizationBehavior<TMessage, TResource, TResponse> — checks resource-bound authorization for IAuthorizeResource<TResource> commands. Inserted by AddResourceAuthorization<TMessage, TResource, TResponse>(IServiceCollection) or AddResourceAuthorization(IServiceCollection, params Assembly[]) immediately before the validation behavior so the loaded resource is checked once per request.
- ValidationBehavior<TMessage, TResponse> — unified
validation stage. Runs Validate() when the message implements it
AND every IMessageValidator<TMessage> registered in DI for the message,
aggregating Error.UnprocessableContent failures into a single response.
External validation sources (e.g., the optional
Trellis.FluentValidationpackage contributesFluentValidationMessageValidatorAdapter<TMessage>viaAddTrellisFluentValidation()) plug in here without an extra pipeline behavior. TransactionalCommandBehavior<TMessage, TResponse>(in the optionalTrellis.EntityFrameworkCorepackage) — runs the handler then callsIUnitOfWork.CommitAsyncon success. Opt in viaAddTrellisUnitOfWork<TContext>()after all other behavior registrations so it lands innermost (closest to the handler).
This array contains the always-on behaviors (ExceptionBehavior<TMessage, TResponse>, TracingBehavior<TMessage, TResponse>, LoggingBehavior<TMessage, TResponse>, AuthorizationBehavior<TMessage, TResponse>, and ValidationBehavior<TMessage, TResponse>). The resource-authorization and transactional behaviors are opt-in and supplied by separate registration helpers. FluentValidation (and any other external validation source) participates inside the existing ValidationBehavior<TMessage, TResponse> via the IMessageValidator<TMessage> abstraction, so it does not occupy its own pipeline slot.
public static IReadOnlyList<Type> PipelineBehaviors { get; }
Property Value
Examples
services.AddMediator(options =>
{
options.Assemblies = [typeof(MyCommand).Assembly];
options.PipelineBehaviors = ServiceCollectionExtensions.PipelineBehaviors.ToArray();
});
Methods
AddResourceAuthorization(IServiceCollection, params Assembly[])
Scans the specified assembly for types implementing IAuthorizeResource<TResource> and automatically registers the ResourceAuthorizationBehavior<TMessage, TResource, TResponse> for each. Also scans and registers all IResourceLoader<TMessage, TResource> implementations and SharedResourceLoaderById<TResource, TId> implementations as scoped services.
[RequiresUnreferencedCode("Assembly scanning requires unreferenced types. Use explicit registration for AOT/trimming scenarios.")]
[RequiresDynamicCode("Constructs closed generic types at runtime. Use explicit registration for AOT scenarios.")]
public static IServiceCollection AddResourceAuthorization(this IServiceCollection services, params Assembly[] assemblies)
Parameters
servicesIServiceCollectionThe service collection.
assembliesAssembly[]The assemblies to scan. Pass both the Application assembly (containing IAuthorizeResource<TResource> commands) and the Acl assembly (containing IResourceLoader<TMessage, TResource> implementations).
Returns
- IServiceCollection
The service collection for chaining.
Examples
// Scans both Application (commands) and Acl (loaders) assemblies
services.AddResourceAuthorization(
typeof(CancelOrderCommand).Assembly,
typeof(CancelOrderResourceLoader).Assembly);
Remarks
For each concrete type that implements IAuthorizeResource<TResource>,
the method extracts TResource and resolves TResponse from
ICommand<TResponse>, IQuery<TResponse>, or
IRequest<TResponse>. It then registers the closed-generic
ResourceAuthorizationBehavior<TMessage, TResource, TResponse>
as IPipelineBehavior<TMessage, TResponse>.
This method also scans for IResourceLoader<TMessage, TResource> implementations and registers them as scoped services, so you don't need to call AddResourceLoaders(IServiceCollection, Assembly) separately.
When a command implements IIdentifyResource<TResource, TId> and no explicit IResourceLoader<TMessage, TResource> is found, a Trellis.Mediator.SharedResourceLoaderAdapter<TMessage, TResource, TId> is automatically registered, bridging to the SharedResourceLoaderById<TResource, TId>. Explicit loaders always take priority.
AddResourceAuthorization<TMessage, TResource, TResponse>(IServiceCollection)
Registers the ResourceAuthorizationBehavior<TMessage, TResource, TResponse> for a specific command/resource pair. Call once per command that implements IAuthorizeResource<TResource>.
public static IServiceCollection AddResourceAuthorization<TMessage, TResource, TResponse>(this IServiceCollection services) where TMessage : IAuthorizeResource<TResource>, IMessage where TResponse : IResult, IFailureFactory<TResponse>
Parameters
servicesIServiceCollectionThe service collection.
Returns
- IServiceCollection
The service collection for chaining.
Type Parameters
TMessageThe command or query type that implements IAuthorizeResource<TResource>.
TResourceThe resource type loaded for authorization.
TResponseThe response type (e.g.,
Result<Order>). Must implement IResult and IFailureFactory<TSelf>.
Examples
services.AddResourceAuthorization<CancelOrderCommand, Order, Result<Order>>();
services.AddScoped<IResourceLoader<CancelOrderCommand, Order>, CancelOrderResourceLoader>();
Remarks
Prefer AddResourceAuthorization(IServiceCollection, params Assembly[]) for automatic discovery. Use this explicit overload for AOT/trimming scenarios where assembly scanning is not available.
Also register the corresponding IResourceLoader<TMessage, TResource> as scoped, either explicitly or via AddResourceLoaders(IServiceCollection, Assembly).
AddResourceLoaders(IServiceCollection, Assembly)
Scans the specified assembly for types implementing IResourceLoader<TMessage, TResource> and registers them as scoped services.
[RequiresUnreferencedCode("Assembly scanning requires unreferenced types. Use explicit registration for AOT/trimming scenarios.")]
public static IServiceCollection AddResourceLoaders(this IServiceCollection services, Assembly assembly)
Parameters
servicesIServiceCollectionThe service collection.
assemblyAssemblyThe assembly to scan for resource loader implementations.
Returns
- IServiceCollection
The service collection for chaining.
Examples
services.AddResourceLoaders(typeof(CancelOrderResourceLoader).Assembly);
AddSharedResourceLoader<TMessage, TResource, TId>(IServiceCollection)
Registers a Trellis.Mediator.SharedResourceLoaderAdapter<TMessage, TResource, TId> for a specific command, bridging to a SharedResourceLoaderById<TResource, TId>. Use this for AOT/trimming scenarios where assembly scanning is not available.
public static IServiceCollection AddSharedResourceLoader<TMessage, TResource, TId>(this IServiceCollection services) where TMessage : IAuthorizeResource<TResource>, IIdentifyResource<TResource, TId>
Parameters
servicesIServiceCollectionThe service collection.
Returns
- IServiceCollection
The service collection for chaining.
Type Parameters
TMessageThe command type implementing IAuthorizeResource<TResource> and IIdentifyResource<TResource, TId>.
TResourceThe resource type.
TIdThe identifier type.
Examples
services.AddScoped<SharedResourceLoaderById<Order, OrderId>, OrderResourceLoader>();
services.AddSharedResourceLoader<CancelOrderCommand, Order, OrderId>();
services.AddSharedResourceLoader<ReturnOrderCommand, Order, OrderId>();
Remarks
The SharedResourceLoaderById<TResource, TId> implementation must be registered
separately (e.g., services.AddScoped<SharedResourceLoaderById<Order, OrderId>, OrderResourceLoader>()).
AddTrellisBehaviors(IServiceCollection)
Registers Trellis Result-aware pipeline behaviors as open generic
Mediator.IPipelineBehavior<TMessage, TResponse> implementations.
Use this when NOT using MediatorOptions.PipelineBehaviors (non-AOT scenario).
public static IServiceCollection AddTrellisBehaviors(this IServiceCollection services)
Parameters
servicesIServiceCollectionThe service collection.
Returns
- IServiceCollection
The service collection for chaining.
Remarks
Idempotent: calling this method more than once registers each behavior exactly once,
so plug-in extension methods (e.g. AddTrellisFluentValidation, AddTrellisAsp)
that defensively call it as a precondition will not produce duplicate pipeline entries
when the consumer also calls it explicitly.
AddTrellisBehaviors(IServiceCollection, Action<TrellisMediatorTelemetryOptions>)
Registers Trellis pipeline behaviors and configures
TrellisMediatorTelemetryOptions for logging/tracing redaction. Equivalent
to calling AddTrellisBehaviors(IServiceCollection) followed by mutating
the resolved singleton via configure.
public static IServiceCollection AddTrellisBehaviors(this IServiceCollection services, Action<TrellisMediatorTelemetryOptions> configure)
Parameters
servicesIServiceCollectionThe service collection.
configureAction<TrellisMediatorTelemetryOptions>Callback invoked with the singleton telemetry options instance. Use this to opt in to including Detail in log messages and activity descriptions.
Returns
- IServiceCollection
The service collection for chaining.