Skip to content

Commit 93cd6c4

Browse files
committed
Add DI extensions for exception handling
Introduces DependencyInjectionExtensions.cs to provide registration helpers for exception handling services and MediatR pipeline integration. Updates README with usage examples for AddCleanArchitectureExceptions and AddCleanArchitectureExceptionsPipeline.
1 parent efc24b8 commit 93cd6c4

2 files changed

Lines changed: 79 additions & 4 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using CleanArchitecture.Extensions.Exceptions.Behaviors;
2+
using CleanArchitecture.Extensions.Exceptions.Catalog;
3+
using CleanArchitecture.Extensions.Exceptions.Options;
4+
using CleanArchitecture.Extensions.Exceptions.Redaction;
5+
using MediatR;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Microsoft.Extensions.DependencyInjection.Extensions;
8+
9+
namespace CleanArchitecture.Extensions.Exceptions;
10+
11+
/// <summary>
12+
/// Registration helpers for CleanArchitecture.Extensions.Exceptions.
13+
/// </summary>
14+
public static class DependencyInjectionExtensions
15+
{
16+
/// <summary>
17+
/// Registers exception handling services (catalog, redactor, options).
18+
/// </summary>
19+
/// <param name="services">Service collection.</param>
20+
/// <param name="configureHandling">Optional callback to configure <see cref="ExceptionHandlingOptions"/>.</param>
21+
/// <param name="configureCatalog">Optional callback to configure <see cref="ExceptionCatalogOptions"/>.</param>
22+
public static IServiceCollection AddCleanArchitectureExceptions(
23+
this IServiceCollection services,
24+
Action<ExceptionHandlingOptions>? configureHandling = null,
25+
Action<ExceptionCatalogOptions>? configureCatalog = null)
26+
{
27+
ArgumentNullException.ThrowIfNull(services);
28+
29+
var handlingBuilder = services.AddOptions<ExceptionHandlingOptions>();
30+
if (configureHandling is not null)
31+
{
32+
handlingBuilder.Configure(configureHandling);
33+
}
34+
35+
var catalogBuilder = services.AddOptions<ExceptionCatalogOptions>();
36+
if (configureCatalog is not null)
37+
{
38+
catalogBuilder.Configure(configureCatalog);
39+
}
40+
41+
services.TryAddSingleton<IExceptionCatalog, ExceptionCatalog>();
42+
services.TryAddSingleton<ExceptionRedactor>();
43+
44+
return services;
45+
}
46+
47+
/// <summary>
48+
/// Adds the MediatR exception wrapping behavior to the pipeline.
49+
/// </summary>
50+
public static MediatRServiceConfiguration AddCleanArchitectureExceptionsPipeline(
51+
this MediatRServiceConfiguration configuration)
52+
{
53+
ArgumentNullException.ThrowIfNull(configuration);
54+
55+
configuration.AddOpenBehavior(typeof(ExceptionWrappingBehavior<,>));
56+
return configuration;
57+
}
58+
}

src/CleanArchitecture.Extensions.Exceptions/README.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,37 @@ Check NuGet.org for the latest stable or preview version before installing.
2020
Register the behavior in the MediatR pipeline (after validation, before performance logging) and tune the options if needed:
2121

2222
```csharp
23-
using CleanArchitecture.Extensions.Exceptions.Behaviors;
23+
using System.Net;
24+
using CleanArchitecture.Extensions.Exceptions;
2425
using CleanArchitecture.Extensions.Exceptions.Options;
26+
using CleanArchitecture.Extensions.Exceptions.BaseTypes;
27+
using CleanArchitecture.Extensions.Exceptions.Catalog;
2528
using MediatR;
2629

27-
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ExceptionWrappingBehavior<,>));
28-
29-
services.Configure<ExceptionHandlingOptions>(options =>
30+
services.AddCleanArchitectureExceptions(options =>
3031
{
3132
options.IncludeExceptionDetails = false;
3233
options.RethrowExceptionTypes.Add(typeof(OperationCanceledException));
3334
options.EnvironmentName = env.EnvironmentName; // include details/stack in configured environments (e.g., Development)
3435
options.IncludeStackTrace = false;
3536
options.StatusCodeOverrides["ERR.DOMAIN.GENERIC"] = HttpStatusCode.UnprocessableEntity;
3637
});
38+
39+
services.AddMediatR(cfg =>
40+
{
41+
cfg.RegisterServicesFromAssemblyContaining<Program>();
42+
cfg.AddCleanArchitectureExceptionsPipeline();
43+
});
44+
45+
// Optional: configure catalog overrides
46+
services.Configure<ExceptionCatalogOptions>(catalog =>
47+
{
48+
catalog.Descriptors.Add(new ExceptionDescriptor(
49+
typeof(CustomDomainException),
50+
"ERR.DOMAIN.CUSTOM",
51+
"Custom domain failure",
52+
ExceptionSeverity.Error));
53+
});
3754
```
3855

3956
When handlers return `Result`/`Result<T>`, the behavior converts catalogued exceptions into failure results so controllers can return `ProblemDetails` consistently. Configure redaction and retry classification via `ExceptionHandlingOptions` and the catalog if you need stricter policies.

0 commit comments

Comments
 (0)