Skip to content
This repository has been archived by the owner on Feb 15, 2023. It is now read-only.

Commit

Permalink
Merge pull request #77 from remcoros/TryAdd
Browse files Browse the repository at this point in the history
Use TryAdd vs Add to allow multiple calls to AddMediatr(..)
  • Loading branch information
jbogard authored Jun 30, 2020
2 parents 127830d + 22f463f commit a8160b8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,33 @@ private static void Fill<T>(this IList<T> list, T value)

public static void AddRequiredServices(IServiceCollection services, MediatRServiceConfiguration serviceConfiguration)
{
services.AddTransient<ServiceFactory>(p => p.GetService);
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionActionProcessorBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));
services.Add(new ServiceDescriptor(typeof(IMediator), serviceConfiguration.MediatorImplementationType, serviceConfiguration.Lifetime));
// Use TryAdd, so any existing ServiceFactory/IMediator registration doesn't get overriden
services.TryAddTransient<ServiceFactory>(p => p.GetService);
services.TryAdd(new ServiceDescriptor(typeof(IMediator), serviceConfiguration.MediatorImplementationType, serviceConfiguration.Lifetime));

// Use TryAddTransientExact (see below), we dó want to register our Pre/Post processor behavior, even if (a more concrete)
// registration for IPipelineBehavior<,> already exists. But only once.
services.TryAddTransientExact(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.TryAddTransientExact(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));
services.TryAddTransientExact(typeof(IPipelineBehavior<,>), typeof(RequestExceptionActionProcessorBehavior<,>));
services.TryAddTransientExact(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));
}

/// <summary>
/// Adds a new transient registration to the service collection only when no existing registration of the same service type and implementation type exists.
/// In contrast to TryAddTransient, which only checks the service type.
/// </summary>
/// <param name="services">The service collection</param>
/// <param name="serviceType">Service type</param>
/// <param name="implementationType">Implementation type</param>
private static void TryAddTransientExact(this IServiceCollection services, Type serviceType, Type implementationType)
{
if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType))
{
return;
}

services.AddTransient(serviceType, implementationType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,20 @@ public void ShouldResolveNotificationHandlers()
{
_provider.GetServices<INotificationHandler<Pinged>>().Count().ShouldBe(3);
}

[Fact]
public void Can_Call_AddMediatr_multiple_times()
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton(new Logger());
services.AddMediatR(cfg => cfg.Using<MyCustomMediator>(), typeof(CustomMediatorTests));

// Call AddMediatr again, this should NOT override our custom mediatr (With MS DI, last registration wins)
services.AddMediatR(typeof(CustomMediatorTests));

var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
mediator.GetType().ShouldBe(typeof(MyCustomMediator));
}
}
}

0 comments on commit a8160b8

Please sign in to comment.