1. 源码
1.1. 项目 MediatR.Extensions.Microsoft.DependencyInjection
public static IServiceCollection AddMediatR(this IServiceCollection services, params Assembly[] assemblies)
=> services.AddMediatR(assemblies, configuration: null);
public static IServiceCollection AddMediatR(this IServiceCollection services, IEnumerable<Assembly> assemblies, Action<MediatRServiceConfiguration>? configuration)
{
if (!assemblies.Any())
{
throw new ArgumentException("No assemblies found to scan. Supply at least one assembly to scan for handlers.");
}
var serviceConfig = new MediatRServiceConfiguration();
configuration?.Invoke(serviceConfig);
//注册项目默认服务
ServiceRegistrar.AddRequiredServices(services, serviceConfig);
//注册程序集相关接口继承类
ServiceRegistrar.AddMediatRClasses(services, assemblies, serviceConfig);
return services;
}
This registers:
IMediator
as transientIRequestHandler<>
concrete implementations as transientINotificationHandler<>
concrete implementations as transientIStreamRequestHandler<>
concrete implementations as transientIRequestPreProcessor<>
concrete implementations as transientIRequestPostProcessor<,>
concrete implementations as transientIRequestExceptionHandler<,,>
concrete implementations as transientIRequestExceptionAction<,>)
concrete implementations as transient
This also registers open generic implementations for:
INotificationHandler<>
IRequestPreProcessor<>
IRequestPostProcessor<,>
IRequestExceptionHandler<,,>
IRequestExceptionAction<,>
注册泛型
var multiOpenInterfaces = new[]
{
typeof(INotificationHandler<>),
typeof(IRequestPreProcessor<>),
typeof(IRequestPostProcessor<,>),
typeof(IRequestExceptionHandler<,,>),
typeof(IRequestExceptionAction<,>)
};
foreach (var multiOpenInterface in multiOpenInterfaces)
{
var arity = multiOpenInterface.GetGenericArguments().Length;
var concretions = assembliesToScan
.SelectMany(a => a.DefinedTypes)
.Where(type => type.FindInterfacesThatClose(multiOpenInterface).Any())
.Where(type => type.IsConcrete() && type.IsOpenGeneric())
.Where(type => type.GetGenericArguments().Length == arity)
.Where(configuration.TypeEvaluator)
.ToList();
foreach (var type in concretions)
{
services.AddTransient(multiOpenInterface, type);
}
}
IsOpenGeneric
中调用 Type.IsGenericTypeDefinition
判断 是否为泛型
typeof(List<>).IsGenericTypeDefinition true
typeof(List<>).IsGenericTypeDefinition false
//定义委托
public delegate object ServiceFactory(Type serviceType);
//委托扩展方法,factory 相当于 GetRequiredService
public static class ServiceFactoryExtensions
{
public static T GetInstance<T>(this ServiceFactory factory)
=> (T) factory(typeof(T));
public static IEnumerable<T> GetInstances<T>(this ServiceFactory factory)
=> (IEnumerable<T>) factory(typeof(IEnumerable<T>));
}
//工厂方法,传入Microsoft.Extensions.DependencyInjection.IServiceCollection,在接下来的项目中作为解析实例工厂
services.TryAddTransient<ServiceFactory>(p => p.GetRequiredService);
//将IOC自带的GetRequiredService解析为ServiceFactory 委托实例
public static T GetRequiredService<T>(this IServiceProvider provider) where T : notnull;
The difference between GetService() and GetRequiredService() in ASP.NET Core GetRequiredService
找不到服务时会抛出异常,而GetService
会返回null
,建议采用GetRequiredService
RequestHandlerWrapperImpl
类
public override Task<TResponse> Handle(IRequest<TResponse> request, CancellationToken cancellationToken,
ServiceFactory serviceFactory)
{
Task<TResponse> Handler() => GetHandler<IRequestHandler<TRequest, TResponse>>(serviceFactory).Handle((TRequest) request, cancellationToken);
//累加器嵌套调用
return serviceFactory
.GetInstances<IPipelineBehavior<TRequest, TResponse>>()
.Reverse()
.Aggregate((RequestHandlerDelegate<TResponse>) Handler, (next, pipeline) => () => pipeline.Handle((TRequest)request, cancellationToken, next))();
}
NotificationHandlerWrapperImpl
类
public class NotificationHandlerWrapperImpl<TNotification> : NotificationHandlerWrapper
where TNotification : INotification
{
public override Task Handle(INotification notification, CancellationToken cancellationToken, ServiceFactory serviceFactory,
Func<IEnumerable<Func<INotification, CancellationToken, Task>>, INotification, CancellationToken, Task> publish)
{
//linq select 来遍历通知
var handlers = serviceFactory
.GetInstances<INotificationHandler<TNotification>>()
.Select(x => new Func<INotification, CancellationToken, Task>((theNotification, theToken) => x.Handle((TNotification)theNotification, theToken)));
return publish(handlers, notification, cancellationToken);
}
}
2. 总结
扩展按一定的顺序注册程序集中接口继承,再根据request type
反射 相关WrapperImpl
,Wrapper
解析接口,嵌套或遍历执行
IPipelineBehavior
解析 之前注册的 RequestPreProcessorBehavior
和RequestPostProcessorBehavior
,而这两者的构造函数均解析了一组IRequestPreProcessor
和IRequestPostProcessor
,利用上面的累加器嵌套和 next.Handle
执行的位置决定 pre
会在 IRequestHandler
前执行,而 post
则在其之后执行,而非泛型会在泛型之前,这则由扩展注册的顺序(AddMediatRClasses
)决定。
调用的顺序:
Send
根据type构造RequestHandlerWrapperImpl
RequestHandlerWrapperImpl.Handle 解析 IPipelineBehavior
IPipelineBehavior解析一组Processor,并在内部Handle方法中利用**累加器**迭代执行Processor.process
本质上是通过IOC解析和累加器嵌套实现解耦
publish
NotificationHandlerWrapperImpl
INotificationHandler
利用linq Select 遍历执行(通知)INotificationHandler
3. 知识点
3.1. Array
转化为IEnumerable
params Assembly[] assemblies
可以转化为 IEnumerable<Assembly> assemblies
,因为Array
继承了IEnumerable
In the .NET Framework version 2.0, the
Array
class implements theSystem.Collections.Generic.IList<T>
,System.Collections.Generic.ICollection<T>
, andSystem.Collections.Generic.IEnumerable<T>
generic interfaces.
3.2. linq Aggregate
累加器
using System;
using System.Linq;
namespace LINQDemo
{
class Program
{
static void Main(string[] args)
{
int[] intNumbers = { 3, 5, 7, 9 };
int result = intNumbers.Aggregate(2, (n1, n2) => n1 * n2);
Console.WriteLine(result);
Console.ReadKey();
}
}
步骤1:首先乘以(2*3)
得到结果6
步骤2:步骤1的结果,即6乘以5
得到结果30
步骤 3:步骤 2 的结果,即 30,然后乘以 7,得到结果 210。
步骤4:将步骤3的结果,即210乘以9,得到最终结果1890。