diff --git a/src/MediatR/MediatR.csproj b/src/MediatR/MediatR.csproj index a7d948f2..37a40fd6 100644 --- a/src/MediatR/MediatR.csproj +++ b/src/MediatR/MediatR.csproj @@ -4,7 +4,7 @@ Jimmy Bogard Simple, unambitious mediator implementation in .NET Copyright Jimmy Bogard - netstandard2.0 + netstandard2.0;net6.0 enable strict mediator;request;response;queries;commands;notifications @@ -32,7 +32,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/MediatR/Mediator.cs b/src/MediatR/Mediator.cs index adde975e..4d65de18 100644 --- a/src/MediatR/Mediator.cs +++ b/src/MediatR/Mediator.cs @@ -46,11 +46,12 @@ public Task Send(IRequest request, Cancellation throw new ArgumentNullException(nameof(request)); } - var requestType = request.GetType(); - - var handler = (RequestHandlerWrapper)_requestHandlers.GetOrAdd(requestType, - static t => (RequestHandlerBase)(Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(t, typeof(TResponse))) - ?? throw new InvalidOperationException($"Could not create wrapper type for {t}"))); + var handler = (RequestHandlerWrapper)_requestHandlers.GetOrAdd(request.GetType(), static requestType => + { + var wrapperType = typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse)); + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper type for {requestType}"); + return (RequestHandlerBase)wrapper; + }); return handler.Handle(request, _serviceProvider, cancellationToken); } @@ -63,11 +64,12 @@ public Task Send(TRequest request, CancellationToken cancellationToken throw new ArgumentNullException(nameof(request)); } - var requestType = request.GetType(); - - var handler = (RequestHandlerWrapper)_requestHandlers.GetOrAdd(requestType, - static t => (RequestHandlerBase)(Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<>).MakeGenericType(t)) - ?? throw new InvalidOperationException($"Could not create wrapper type for {t}"))); + var handler = (RequestHandlerWrapper)_requestHandlers.GetOrAdd(request.GetType(), static requestType => + { + var wrapperType = typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestType); + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper type for {requestType}"); + return (RequestHandlerBase)wrapper; + }); return handler.Handle(request, _serviceProvider, cancellationToken); } @@ -78,41 +80,31 @@ public Task Send(TRequest request, CancellationToken cancellationToken { throw new ArgumentNullException(nameof(request)); } - var requestType = request.GetType(); - var handler = _requestHandlers.GetOrAdd(requestType, - static requestTypeKey => - { - var requestInterfaceType = requestTypeKey - .GetInterfaces() - .FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>)); - Type wrapperType; + var handler = _requestHandlers.GetOrAdd(request.GetType(), static requestType => + { + Type wrapperType; + var requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>)); + if (requestInterfaceType is null) + { + requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i == typeof(IRequest)); if (requestInterfaceType is null) { - requestInterfaceType = requestTypeKey - .GetInterfaces() - .FirstOrDefault(static i => i == typeof(IRequest)); - - if (requestInterfaceType is null) - { - throw new ArgumentException($"{requestTypeKey.Name} does not implement {nameof(IRequest)}", - nameof(request)); - } - - wrapperType = - typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestTypeKey); - } - else - { - var responseType = requestInterfaceType.GetGenericArguments()[0]; - wrapperType = - typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestTypeKey, responseType); + throw new ArgumentException($"{requestType.Name} does not implement {nameof(IRequest)}", nameof(request)); } - return (RequestHandlerBase)(Activator.CreateInstance(wrapperType) - ?? throw new InvalidOperationException($"Could not create wrapper for type {wrapperType}")); - }); + wrapperType = typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestType); + } + else + { + var responseType = requestInterfaceType.GetGenericArguments()[0]; + wrapperType = typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, responseType); + } + + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {requestType}"); + return (RequestHandlerBase)wrapper; + }); // call via dynamic dispatch to avoid calling through reflection for performance reasons return handler.Handle(request, _serviceProvider, cancellationToken); @@ -149,10 +141,12 @@ protected virtual Task PublishCore(IEnumerable hand private Task PublishNotification(INotification notification, CancellationToken cancellationToken = default) { - var notificationType = notification.GetType(); - var handler = _notificationHandlers.GetOrAdd(notificationType, - static t => (NotificationHandlerWrapper) (Activator.CreateInstance(typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(t)) - ?? throw new InvalidOperationException($"Could not create wrapper for type {t}"))); + var handler = _notificationHandlers.GetOrAdd(notification.GetType(), static notificationType => + { + var wrapperType = typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(notificationType); + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {notificationType}"); + return (NotificationHandlerWrapper)wrapper; + }); return handler.Handle(notification, _serviceProvider, PublishCore, cancellationToken); } @@ -165,10 +159,12 @@ public IAsyncEnumerable CreateStream(IStreamRequest) _streamRequestHandlers.GetOrAdd(requestType, - t => (StreamRequestHandlerBase) Activator.CreateInstance(typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse)))); + var streamHandler = (StreamRequestHandlerWrapper)_streamRequestHandlers.GetOrAdd(request.GetType(), static requestType => + { + var wrapperType = typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse)); + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {requestType}"); + return (StreamRequestHandlerBase)wrapper; + }); var items = streamHandler.Handle(request, _serviceProvider, cancellationToken); @@ -183,26 +179,20 @@ public IAsyncEnumerable CreateStream(IStreamRequest + var handler = _streamRequestHandlers.GetOrAdd(request.GetType(), static requestType => + { + var requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStreamRequest<>)); + if (requestInterfaceType is null) { - var requestInterfaceType = requestTypeKey - .GetInterfaces() - .FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStreamRequest<>)); - var isValidRequest = requestInterfaceType != null; + throw new ArgumentException($"{requestType.Name} does not implement IStreamRequest", nameof(request)); + } - if (!isValidRequest) - { - throw new ArgumentException($"{requestType.Name} does not implement IStreamRequest", nameof(requestTypeKey)); - } + var responseType = requestInterfaceType.GetGenericArguments()[0]; + var wrapperType = typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestType, responseType); + var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {requestType}"); + return (StreamRequestHandlerBase)wrapper; + }); - var responseType = requestInterfaceType!.GetGenericArguments()[0]; - return (StreamRequestHandlerBase) Activator.CreateInstance(typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestTypeKey, responseType)); - }); - - // call via dynamic dispatch to avoid calling through reflection for performance reasons var items = handler.Handle(request, _serviceProvider, cancellationToken); return items; diff --git a/src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs b/src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs index c644dd71..9952b53c 100644 --- a/src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs +++ b/src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs @@ -1,6 +1,7 @@ namespace MediatR.Pipeline; using Internal; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; @@ -71,7 +72,7 @@ private static IEnumerable GetExceptionTypes(Type? exceptionType) var exceptionActionInterfaceType = typeof(IRequestExceptionAction<,>).MakeGenericType(typeof(TRequest), exceptionType); var enumerableExceptionActionInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionActionInterfaceType); - var actionsForException = (IEnumerable)_serviceProvider.GetService(enumerableExceptionActionInterfaceType); + var actionsForException = (IEnumerable)_serviceProvider.GetRequiredService(enumerableExceptionActionInterfaceType); return HandlersOrderer.Prioritize(actionsForException.ToList(), request) .Select(action => (exceptionType, action)); diff --git a/src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs b/src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs index 362f3f26..2139f81d 100644 --- a/src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs +++ b/src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs @@ -1,6 +1,7 @@ namespace MediatR.Pipeline; using Internal; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; @@ -88,7 +89,7 @@ private static IEnumerable GetExceptionTypes(Type? exceptionType) var exceptionHandlerInterfaceType = typeof(IRequestExceptionHandler<,,>).MakeGenericType(typeof(TRequest), typeof(TResponse), exceptionType); var enumerableExceptionHandlerInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionHandlerInterfaceType); - var exceptionHandlers = (IEnumerable) _serviceProvider.GetService(enumerableExceptionHandlerInterfaceType); + var exceptionHandlers = (IEnumerable) _serviceProvider.GetRequiredService(enumerableExceptionHandlerInterfaceType); return HandlersOrderer.Prioritize(exceptionHandlers.ToList(), request) .Select(handler => (exceptionType, action: handler)); diff --git a/src/MediatR/Registration/ServiceRegistrar.cs b/src/MediatR/Registration/ServiceRegistrar.cs index de3d920b..8c6a32c8 100644 --- a/src/MediatR/Registration/ServiceRegistrar.cs +++ b/src/MediatR/Registration/ServiceRegistrar.cs @@ -105,7 +105,7 @@ private static void ConnectImplementationsToTypesClosing(Type openRequestInterfa } } - private static bool IsMatchingWithInterface(Type handlerType, Type handlerInterface) + private static bool IsMatchingWithInterface(Type? handlerType, Type handlerInterface) { if (handlerType == null || handlerInterface == null) { @@ -186,15 +186,15 @@ var interfaceType in yield return interfaceType; } } - else if (pluggedType.GetTypeInfo().BaseType.GetTypeInfo().IsGenericType && - (pluggedType.GetTypeInfo().BaseType.GetGenericTypeDefinition() == templateType)) + else if (pluggedType.GetTypeInfo().BaseType!.GetTypeInfo().IsGenericType && + (pluggedType.GetTypeInfo().BaseType!.GetGenericTypeDefinition() == templateType)) { - yield return pluggedType.GetTypeInfo().BaseType; + yield return pluggedType.GetTypeInfo().BaseType!; } if (pluggedType.GetTypeInfo().BaseType == typeof(object)) yield break; - foreach (var interfaceType in FindInterfacesThatClosesCore(pluggedType.GetTypeInfo().BaseType, templateType)) + foreach (var interfaceType in FindInterfacesThatClosesCore(pluggedType.GetTypeInfo().BaseType!, templateType)) { yield return interfaceType; }