[Abp vNext 源码分析] - 13. 本地事件总线与分布式事件总线 (Rabbit MQ) (2)

可以看到,这里传递了一个 SingleInstanceHandlerFactory 对象,这玩意儿是干嘛用的呢?从名字可以看出来,这是一个工厂,是用来创建 Handler (事件处理器) 的工厂,并且是一个单实例的事件处理器工厂。

下面就是 IEventHandlerFactory 接口的定义,以及 SingleInstanceHandlerFactory 实现。

public interface IEventHandlerFactory { // 获得一个事件处理器包装对象,即事件处理器执行完毕之后,可以调用 // IEventHandlerDisposeWrapper.Dispose() 进行释放。 IEventHandlerDisposeWrapper GetHandler(); // 判断在已有的事件处理器工厂集合中,是否已经存在了相同的事件处理器。 bool IsInFactories(List<IEventHandlerFactory> handlerFactories); } public class SingleInstanceHandlerFactory : IEventHandlerFactory { // 构造工厂时,传递的事件处理器实例。 public IEventHandler HandlerInstance { get; } public SingleInstanceHandlerFactory(IEventHandler handler) { HandlerInstance = handler; } // 通过 EventHandlerDisposeWrapper 包装事件处理器实例。 public IEventHandlerDisposeWrapper GetHandler() { return new EventHandlerDisposeWrapper(HandlerInstance); } // 判断针对 HandlerInstance 的事件处理器是否已经存在。 public bool IsInFactories(List<IEventHandlerFactory> handlerFactories) { return handlerFactories .OfType<SingleInstanceHandlerFactory>() .Any(f => f.HandlerInstance == HandlerInstance); } }

针对 IEventHandlerFactory 工厂,还拥有 3 个不同的实现,下表分别说明它们的应用场景。

[Abp vNext 源码分析] - 13. 本地事件总线与分布式事件总线 (Rabbit MQ)

实现类型 作用
IocEventHandlerFactory   每个工厂对应一个事件处理器的的类型,并通过 ScopeFactory 解析具体的事件处理器。生命周期由 scope 控制,当 scope 释放时,对应的事件处理器实例也会被销毁。  
SingleInstanceHandlerFactory   每个工厂对应单独的一个事件处理器实例,事件处理器实例是由创建者控制的。  
TransientEventHandlerFactory   每个工厂对应一个事件处理器的类型,区别是它不由 IoC 解析实例,而是使用的 Activator.CreateInstance() 方法构造实例,是一个瞬时对象,调用包装器的 Dispose 即会进行释放。  
TransientEventHandlerFactory<THandler>   每个工厂对应指定的 THandler 事件处理器,生命周期同上面的工厂一样。  

这几种工厂都是在订阅操作时,不同的订阅重载使用不同的工厂,或者是自己指定事件处理器的工厂均可。

public virtual IDisposable Subscribe<TEvent, THandler>() where TEvent : class where THandler : IEventHandler, new() { return Subscribe(typeof(TEvent), new TransientEventHandlerFactory<THandler>()); } public virtual IDisposable Subscribe(Type eventType, IEventHandler handler) { return Subscribe(eventType, new SingleInstanceHandlerFactory(handler)); }

不过有一种特殊的行为,开发人员可以 不用显式订阅。在 EventBus 类型中,定义了一个 SubscribeHandlers(ITypeList<IEventHandler> handlers) 方法。该方法接收一个类型集合,通过遍历集合,从事件处理器的定义当中,取得事件处理器监听的事件类型 TEvent。

在取得了事件类型,并知晓了事件处理器类型以后,事件总线就可以订阅 TEvent 类型的事件,并使用 IocEventHandlerFactory 工厂来构造事件处理器。

protected virtual void SubscribeHandlers(ITypeList<IEventHandler> handlers) { // 遍历事件处理器的类型,其实这里的就是模块启动时,传递给 XXXOptions 的集合。 foreach (var handler in handlers) { // 获得事件处理器的所有接口定义,并遍历接口进行检查。 var interfaces = handler.GetInterfaces(); foreach (var @interface in interfaces) { // 如果接口没有实现 IEventHandler 类型,则忽略。 if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface)) { continue; } // 从泛型参数当中,获得定义的事件类型。 var genericArgs = @interface.GetGenericArguments(); // 泛型参数完全匹配 1 时,才进行订阅操作。 if (genericArgs.Length == 1) { Subscribe(genericArgs[0], new IocEventHandlerFactory(ServiceScopeFactory, handler)); } } } }

这个订阅方法在 EventBus 当中是一个抽象方法,分别在本地事件总线和分布式事件总线有实现,这里我们首先讲解本地事件的逻辑。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspdgg.html