文档:html
EventBus是一个单例对象,被全部类触发事件或处理事件时共享。数据库
IEventBusConfiguration在应用启动时加载(by AbpCoreInstaller),依据它的配置决定 是全部IWindsorContainer实例共享同一条事件总线(EventBus.Default),仍是每一个IWindsorContainer实例建立一个本身的单例。默认使用EventBus.Default。
框架
由于在应用中IocManager使用单例,IIocManager.IocContainer也是单一的,因此事件总线使用的就是EventBus.Default。dom
使用属性注入模式:async
public class TaskAppService : ApplicationService { public IEventBus EventBus { get; set; } public TaskAppService() { EventBus = NullEventBus.Instance; } }
若是你不能注入它,能够直接使用EventBus.Default。使用方式以下所示:ide
EventBus.Default.Trigger(...); //trigger an event
但就如同不推荐使用IocManager.Instance同样,在任何可能的地方都不建议直接使用EventBus.Default,由于它难于单元测试。源码分析
在触发一个事件前,你首先要定义它,经过一个继承自EventData的类来表现一个事件。单元测试
假设当一个任务完成后咱们想触发一个事件:测试
public class TaskCompletedEventData : EventData { public int TaskId { get; set; } }
这个类包含处理事件类所须要的属性,EventData类定义了EventSource(事件源,哪一个对象触发了事件)和EventTime(什么时候触发的)属性。
this
public class EntityEventData<TEntity> : EventData , IEventDataWithInheritableGenericArgument { /// <summary> /// Related entity with this event. /// </summary> public TEntity Entity { get; private set; } /// <summary> /// Constructor. /// </summary> /// <param name="entity">Related entity with this event</param> public EntityEventData(TEntity entity) { Entity = entity; } public virtual object[] GetConstructorArgs() { return new object[] { Entity }; } }
命名空间Event.Bus.Exceptions中定义了ExceptionData 和 AbpHandledExceptionData,当ABP自动处理任何异常时,会触发后者。
命名空间Abp.Events.Bus.Entities中为实体修改提供了泛型的事件:EntityCreationEventData
“ing”事件(例如EntityUpdating)在保存修改(SaveChanges)前触发,因此你能够在这些事件里,经过抛出异常,促使工做单元回滚,阻止操做)。“ed”事件(例如EntityUpdated)在保存修改以后被触发,也就没有机会让工做单元回滚了。
public class TaskAppService : ApplicationService { public IEventBus EventBus { get; set; } public TaskAppService() { EventBus = NullEventBus.Instance; } public void CompleteTask(CompleteTaskInput input) { //TODO: complete the task on database... EventBus.Trigger(new TaskCompletedEventData {TaskId = 42}); } }
Trigger方法有几个重载:
EventBus.Trigger<TaskCompletedEventData>(new TaskCompletedEventData { TaskId = 42 }); //Explicitly declare generic argument EventBus.Trigger(this, new TaskCompletedEventData { TaskId = 42 }); //Set 'event source' as 'this' EventBus.Trigger(typeof(TaskCompletedEventData), this, new TaskCompletedEventData { TaskId = 42 }); //Call non-generic version (first argument is the type of the event class)
在插入、更新或删除实体时,它们被ABP自动触发。若是你有一个Person实体,你能够注册EntityCreatedEventData
参阅 ABP框架 - 实体 ,使用AggregateRoot类的DomainEvents集合。
AbpDbContext in Abp.EntityFramework
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken) { try { var changeReport = ApplyAbpConcepts(); var result = await base.SaveChangesAsync(cancellationToken); await EntityChangeEventHelper.TriggerEventsAsync(changeReport); return result; } catch (DbEntityValidationException ex) { LogDbEntityValidationException(ex); throw; } } protected virtual EntityChangeReport ApplyAbpConcepts() { var changeReport = new EntityChangeReport(); var userId = GetAuditUserId(); var entries = ChangeTracker.Entries().ToList(); foreach (var entry in entries) { switch (entry.State) { case EntityState.Added: CheckAndSetId(entry.Entity); CheckAndSetMustHaveTenantIdProperty(entry.Entity); CheckAndSetMayHaveTenantIdProperty(entry.Entity); SetCreationAuditProperties(entry.Entity, userId); changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Created)); break; case EntityState.Modified: SetModificationAuditProperties(entry, userId); if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted) { SetDeletionAuditProperties(entry.Entity, userId); changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); } else { changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Updated)); } break; case EntityState.Deleted: CancelDeletionForSoftDelete(entry); SetDeletionAuditProperties(entry.Entity, userId); changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); break; } AddDomainEvents(changeReport.DomainEvents, entry.Entity); } return changeReport; } protected virtual void AddDomainEvents(List<DomainEventEntry> domainEvents, object entityAsObj) { var generatesDomainEventsEntity = entityAsObj as IGeneratesDomainEvents; if (generatesDomainEventsEntity == null) { return; } if (generatesDomainEventsEntity.DomainEvents.IsNullOrEmpty()) { return; } domainEvents.AddRange(generatesDomainEventsEntity.DomainEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData))); generatesDomainEventsEntity.DomainEvents.Clear(); }
EntityChangeEventHelper in Abp.Events.Bus.Entities
public class EntityChangeEventHelper : ITransientDependency, IEntityChangeEventHelper { public IEventBus EventBus { get; set; } private readonly IUnitOfWorkManager _unitOfWorkManager; public EntityChangeEventHelper(IUnitOfWorkManager unitOfWorkManager) { _unitOfWorkManager = unitOfWorkManager; EventBus = NullEventBus.Instance; } public virtual void TriggerEvents(EntityChangeReport changeReport) { TriggerEventsInternal(changeReport); if (changeReport.IsEmpty() || _unitOfWorkManager.Current == null) { return; } _unitOfWorkManager.Current.SaveChanges(); } public Task TriggerEventsAsync(EntityChangeReport changeReport) { TriggerEventsInternal(changeReport); if (changeReport.IsEmpty() || _unitOfWorkManager.Current == null) { return Task.FromResult(0); } return _unitOfWorkManager.Current.SaveChangesAsync(); } public virtual void TriggerEntityCreatingEvent(object entity) { TriggerEventWithEntity(typeof(EntityCreatingEventData<>), entity, true); } public virtual void TriggerEntityCreatedEventOnUowCompleted(object entity) { TriggerEventWithEntity(typeof(EntityCreatedEventData<>), entity, false); } public virtual void TriggerEntityUpdatingEvent(object entity) { TriggerEventWithEntity(typeof(EntityUpdatingEventData<>), entity, true); } public virtual void TriggerEntityUpdatedEventOnUowCompleted(object entity) { TriggerEventWithEntity(typeof(EntityUpdatedEventData<>), entity, false); } public virtual void TriggerEntityDeletingEvent(object entity) { TriggerEventWithEntity(typeof(EntityDeletingEventData<>), entity, true); } public virtual void TriggerEntityDeletedEventOnUowCompleted(object entity) { TriggerEventWithEntity(typeof(EntityDeletedEventData<>), entity, false); } public virtual void TriggerEventsInternal(EntityChangeReport changeReport) { TriggerEntityChangeEvents(changeReport.ChangedEntities); TriggerDomainEvents(changeReport.DomainEvents); } protected virtual void TriggerEntityChangeEvents(List<EntityChangeEntry> changedEntities) { foreach (var changedEntity in changedEntities) { switch (changedEntity.ChangeType) { case EntityChangeType.Created: TriggerEntityCreatingEvent(changedEntity.Entity); TriggerEntityCreatedEventOnUowCompleted(changedEntity.Entity); break; case EntityChangeType.Updated: TriggerEntityUpdatingEvent(changedEntity.Entity); TriggerEntityUpdatedEventOnUowCompleted(changedEntity.Entity); break; case EntityChangeType.Deleted: TriggerEntityDeletingEvent(changedEntity.Entity); TriggerEntityDeletedEventOnUowCompleted(changedEntity.Entity); break; default: throw new AbpException("Unknown EntityChangeType: " + changedEntity.ChangeType); } } } protected virtual void TriggerDomainEvents(List<DomainEventEntry> domainEvents) { foreach (var domainEvent in domainEvents) { EventBus.Trigger(domainEvent.EventData.GetType(), domainEvent.SourceEntity, domainEvent.EventData); } } protected virtual void TriggerEventWithEntity(Type genericEventType, object entity, bool triggerInCurrentUnitOfWork) { var entityType = entity.GetType(); var eventType = genericEventType.MakeGenericType(entityType); if (triggerInCurrentUnitOfWork || _unitOfWorkManager.Current == null) { EventBus.Trigger(eventType, (IEventData)Activator.CreateInstance(eventType, new[] { entity })); return; } _unitOfWorkManager.Current.Completed += (sender, args) => EventBus.Trigger(eventType, (IEventData)Activator.CreateInstance(eventType, new[] { entity })); } }
处理一个事件,只要提供一个实现IEventHandler
public class ActivityWriter : IEventHandler<TaskCompletedEventData>, ITransientDependency { public void HandleEvent(TaskCompletedEventData eventData) { WriteActivity("A task is completed by id = " + eventData.TaskId); } }
上例由于实现了ITransientDependency,它会被注册到Ioc容器,而ABP也会自动把它们注册到事件总线,当一个事件发生,ABP使用Ioc容器获得处理程序的引用,并在事件处理后释放该引用。在ABP里,这是使用事件总线的推荐的方式。
internal class EventBusInstaller : IWindsorInstaller { //…… public void Install(IWindsorContainer container, IConfigurationStore store) { if (_eventBusConfiguration.UseDefaultEventBus) { container.Register( Component.For<IEventBus>().UsingFactoryMethod(() => EventBus.Default).LifestyleSingleton() ); } else { container.Register( Component.For<IEventBus>().ImplementedBy<EventBus>().LifestyleSingleton() ); } _eventBus = container.Resolve<IEventBus>(); container.Kernel.ComponentRegistered += Kernel_ComponentRegistered; } private void Kernel_ComponentRegistered(string key, IHandler handler) { if (!typeof(IEventHandler).IsAssignableFrom(handler.ComponentModel.Implementation)) { return; } var interfaces = handler.ComponentModel.Implementation.GetInterfaces(); foreach (var @interface in interfaces) { if (!typeof(IEventHandler).IsAssignableFrom(@interface)) { continue; } var genericArgs = @interface.GetGenericArguments(); if (genericArgs.Length == 1) { _eventBus.Register(genericArgs[0], new IocHandlerFactory(_iocResolver, handler.ComponentModel.Implementation)); } } } } public class IocHandlerFactory : IEventHandlerFactory { public Type HandlerType { get; private set; } private readonly IIocResolver _iocResolver; public IocHandlerFactory(IIocResolver iocResolver, Type handlerType) { _iocResolver = iocResolver; HandlerType = handlerType; } public IEventHandler GetHandler() { return (IEventHandler)_iocResolver.Resolve(HandlerType); } public void ReleaseHandler(IEventHandler handler) { _iocResolver.Release(handler); } }
public class EventBus : IEventBus { /// <inheritdoc/> public IDisposable Register<TEventData>(Action<TEventData> action) where TEventData : IEventData { return Register(typeof(TEventData), new ActionEventHandler<TEventData>(action)); } /// <inheritdoc/> public IDisposable Register<TEventData>(IEventHandler<TEventData> handler) where TEventData : IEventData { return Register(typeof(TEventData), handler); } /// <inheritdoc/> public IDisposable Register<TEventData, THandler>() where TEventData : IEventData where THandler : IEventHandler<TEventData>, new() { return Register(typeof(TEventData), new TransientEventHandlerFactory<THandler>()); } /// <inheritdoc/> public IDisposable Register(Type eventType, IEventHandler handler) { return Register(eventType, new SingleInstanceHandlerFactory(handler)); } /// <inheritdoc/> public IDisposable Register<TEventData>(IEventHandlerFactory handlerFactory) where TEventData : IEventData { return Register(typeof(TEventData), handlerFactory); } /// <inheritdoc/> public IDisposable Register(Type eventType, IEventHandlerFactory handlerFactory) { GetOrCreateHandlerFactories(eventType) .Locking(factories => factories.Add(handlerFactory)); return new FactoryUnregistrar(this, eventType, handlerFactory); }
事件总线的Register方法有几个重载,也就提供了多种注册方式。
EventBus.Register<TaskCompletedEventData>(eventData => { WriteActivity("A task is completed by id = " + eventData.TaskId); });
处理程序
internal class ActionEventHandler<TEventData> : IEventHandler<TEventData>, ITransientDependency { /// <summary> /// Action to handle the event. /// </summary> public Action<TEventData> Action { get; private set; } /// <summary> /// Creates a new instance of <see cref="ActionEventHandler{TEventData}"/>. /// </summary> /// <param name="handler">Action to handle the event</param> public ActionEventHandler(Action<TEventData> handler) { Action = handler; } /// <summary> /// Handles the event. /// </summary> /// <param name="eventData"></param> public void HandleEvent(TEventData eventData) { Action(eventData); } }
EventBus.Register<TaskCompletedEventData>(new ActivityWriter());
注册为一个SingleInstanceHandlerFactory
internal class SingleInstanceHandlerFactory : IEventHandlerFactory { public IEventHandler HandlerInstance { get; private set; } public SingleInstanceHandlerFactory(IEventHandler handler) { HandlerInstance = handler; } public IEventHandler GetHandler() { return HandlerInstance; } public void ReleaseHandler(IEventHandler handler) { } }
EventBus.Register<TaskCompletedEventData, ActivityWriter>();
注册为一个TransientEventHandlerFactory
internal class TransientEventHandlerFactory<THandler> : IEventHandlerFactory where THandler : IEventHandler, new() { public IEventHandler GetHandler() { return new THandler(); } public void ReleaseHandler(IEventHandler handler) { if (handler is IDisposable) { (handler as IDisposable).Dispose(); } } }
上面的几种注册方式,最终都是在间接调用下面这个方法
public IDisposable Register(Type eventType, IEventHandlerFactory handlerFactory) { GetOrCreateHandlerFactories(eventType) .Locking(factories => factories.Add(handlerFactory)); return new FactoryUnregistrar(this, eventType, handlerFactory); }
最简单的方式就是释放Register方法返回的值
//Register to an event... var registration = EventBus.Register<TaskCompletedEventData>(eventData => WriteActivity("A task is completed by id = " + eventData.TaskId) ); //Unregister from event registration.Dispose();
Unregister方法
//Create a handler var handler = new ActivityWriter(); //Register to the event EventBus.Register<TaskCompletedEventData>(handler); //Unregister from event EventBus.Unregister<TaskCompletedEventData>(handler);
UnregisterAll()方法反注册全部事件的全部处理程序。