Skip to content

Commit

Permalink
Merge pull request #1057 from zachpainter77/master
Browse files Browse the repository at this point in the history
Make Auto Registration of Generic Handlers OPT-IN
  • Loading branch information
jbogard committed Sep 9, 2024
2 parents cac76be + 32b512e commit fb30902
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class MediatRServiceConfiguration
/// <summary>
/// Flag that controlls whether MediatR will attempt to register handlers that containg generic type parameters.
/// </summary>
public bool RegisterGenericHandlers { get; set; } = true;
public bool RegisterGenericHandlers { get; set; } = false;

/// <summary>
/// Register various handlers from assembly containing given type
Expand Down
5 changes: 1 addition & 4 deletions src/MediatR/Registration/ServiceRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,7 @@ private static (Type Service, Type Implementation) GetConcreteRegistrationTypes(
var constraintsForEachParameter = openRequestHandlerImplementation
.GetGenericArguments()
.Select(x => x.GetGenericParameterConstraints())
.ToList();

if (constraintsForEachParameter.Count > 2 && constraintsForEachParameter.Any(constraints => !constraints.Where(x => x.IsInterface || x.IsClass).Any()))
throw new ArgumentException($"Error registering the generic handler type: {openRequestHandlerImplementation.FullName}. When registering generic requests with more than two type parameters, each type parameter must have at least one constraint of type interface or class.");
.ToList();

var typesThatCanCloseForEachParameter = constraintsForEachParameter
.Select(constraints => assembliesToScan
Expand Down
23 changes: 5 additions & 18 deletions test/MediatR.Tests/GenericRequestHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public void ShouldResolveAllCombinationsOfGenericHandler(int numberOfClasses, in
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblies(dynamicAssembly);
cfg.RegisterGenericHandlers = true;
});

var provider = services.BuildServiceProvider();
Expand Down Expand Up @@ -93,24 +94,6 @@ public void ShouldNotRegisterDuplicateHandlers(int numberOfClasses, int numberOf
hasDuplicates.ShouldBeFalse();
}

[Fact]
public void ShouldThrowExceptionWhenRegisterningHandlersWithNoConstraints()
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton(new Logger());

var assembly = GenerateMissingConstraintsAssembly();

Should.Throw<ArgumentException>(() =>
{
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(assembly);
});
})
.Message.ShouldContain("When registering generic requests with more than two type parameters, each type parameter must have at least one constraint of type interface or class.");
}

[Fact]
public void ShouldThrowExceptionWhenTypesClosingExceedsMaximum()
{
Expand All @@ -124,6 +107,7 @@ public void ShouldThrowExceptionWhenTypesClosingExceedsMaximum()
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(assembly);
cfg.RegisterGenericHandlers = true;
});
})
.Message.ShouldContain("One of the generic type parameter's count of types that can close exceeds the maximum length allowed");
Expand All @@ -142,6 +126,7 @@ public void ShouldThrowExceptionWhenGenericHandlerRegistrationsExceedsMaximum()
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(assembly);
cfg.RegisterGenericHandlers = true;
});
})
.Message.ShouldContain("The total number of generic type registrations exceeds the maximum allowed");
Expand All @@ -160,6 +145,7 @@ public void ShouldThrowExceptionWhenGenericTypeParametersExceedsMaximum()
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(assembly);
cfg.RegisterGenericHandlers = true;
});
})
.Message.ShouldContain("The number of generic type parameters exceeds the maximum allowed");
Expand All @@ -181,6 +167,7 @@ public void ShouldThrowExceptionWhenTimeoutOccurs()
cfg.MaxGenericTypeRegistrations = 0;
cfg.MaxTypesClosing = 0;
cfg.RegistrationTimeout = 1000;
cfg.RegisterGenericHandlers = true;
cfg.RegisterServicesFromAssembly(assembly);
});
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ public AssemblyResolutionTests()
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton(new Logger());
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly));
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);
cfg.RegisterGenericHandlers = true;
});
_provider = services.BuildServiceProvider();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
namespace MediatR.Tests.MicrosoftExtensionsDI
{
public abstract class BaseGenericRequestHandlerTests
{

protected static Assembly GenerateMissingConstraintsAssembly() =>
CreateAssemblyModuleBuilder("MissingConstraintsAssembly", 3, 3, CreateHandlerForMissingConstraintsTest);

{
protected static Assembly GenerateTypesClosingExceedsMaximumAssembly() =>
CreateAssemblyModuleBuilder("ExceedsMaximumTypesClosingAssembly", 201, 1, CreateHandlerForExceedsMaximumClassesTest);

Expand Down
21 changes: 17 additions & 4 deletions test/MediatR.Tests/SendTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ public SendTests()
{
_dependency = new Dependency();
var services = new ServiceCollection();
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly));
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly);
cfg.RegisterGenericHandlers = true;
});
services.AddSingleton(_dependency);
_serviceProvider = services.BuildServiceProvider();
_mediator = _serviceProvider.GetService<IMediator>()!;
Expand Down Expand Up @@ -248,8 +252,13 @@ public async Task Should_resolve_closed_handler_if_defined()
{
var dependency = new Dependency();
var services = new ServiceCollection();
services.AddSingleton(dependency);
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
services.AddSingleton(dependency);
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());
cfg.RegisterGenericHandlers = true;
});

services.AddTransient<IRequestHandler<VoidGenericPing<PongExtension>>,TestClass1PingRequestHandler>();
var serviceProvider = services.BuildServiceProvider();
var mediator = serviceProvider.GetService<IMediator>()!;
Expand All @@ -267,7 +276,11 @@ public async Task Should_resolve_open_handler_if_not_defined()
var dependency = new Dependency();
var services = new ServiceCollection();
services.AddSingleton(dependency);
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());
cfg.RegisterGenericHandlers = true;
});
services.AddTransient<IRequestHandler<VoidGenericPing<PongExtension>>, TestClass1PingRequestHandler>();
var serviceProvider = services.BuildServiceProvider();
var mediator = serviceProvider.GetService<IMediator>()!;
Expand Down

0 comments on commit fb30902

Please sign in to comment.