• ABP的事件总线和领域事件(EventBus & Domain Events)


    http://www.aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events

    EventBus

    EventBus是个单例,获得EventBus的引用可有下面两个方法:

    默认的EventBus实例,使用EventBus.Default即可找到它。
    EventBus.Default.Trigger(...); //trigger an event

     

    为单元测试考虑,更好的做法是通过依赖注入,获得EventBus的引用,下面是通过属性注入的代码:

     

    public class TaskAppService : ApplicationService
    {
        public IEventBus EventBus { get; set; }
            
        public TaskAppService()
        {
            EventBus = NullEventBus.Instance;
        }
    }
    
    

    使用属性注入比通过构造函数注入更好。上面代码令EventBus初始化为 NullEventBus.Instance,跟ILogger一样的做法。可以参考https://en.wikipedia.org/wiki/Null_Object_pattern对Null对象模式的详细介绍。

     
    自定义事件
     

    让事件类继承于EventData:

    public class TaskCompletedEventData : EventData
    {
        public int TaskId { get; set; }
    }

    EventData class defines EventSource (which object triggered the event) and EventTime(when it's triggered) properties.

    EventData类定义了EventSource (触发事件的源对象)和EventTime(何时触发)属性。

     
    ABP已经定义好的事件

     

    ASP.NET Boilerplate defines AbpHandledExceptionData and triggers this event when it automatically handles any exception. This is especially useful if you want to get more information about exceptions (even ASP.NET Boilerplate automatically logs all exceptions). You can register to this event to be informed when an exception occurs.

    There are also generic event data classes for entity changes: EntityCreatedEventData<TEntity>, EntityUpdatedEventData<TEntity> and EntityDeletedEventData<TEntity>. They are defined in Abp.Events.Bus.Entities namespace. These events are automatically triggered by ASP.NET Boilerplate when an entity is inserted, updated or deleted. If you have a Person entity, can register to EntityCreatedEventData<Person> to be informed when a new Person created and inserted to database. These events also supports inheritance. If Student class derived from Person class and you registered to EntityCreatedEventData<Person>, you will be informed when a Person or Student inserted.

     

    触发事件

    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)
    

     

    处理事件

    需要实现IEventHandler<T>
    public class ActivityWriter : IEventHandler<TaskCompletedEventData>, ITransientDependency
    {
        public void HandleEvent(TaskCompletedEventData eventData)
        {
            WriteActivity("A task is completed by id = " + eventData.TaskId);
        }
    }

    EventBus is integrated with dependency injection system. As we implemented ITransientDependency above, when a TaskCompleted event occured, it creates a new instance of ActivityWriter class and calls it's HandleEvent method, then disposes it. See dependency injection for more.

     

    处理单个事件

    Eventbus支持事件的继承:
    public class TaskEventData : EventData
    {
        public Task Task { get; set; }
    }
    
    public class TaskCreatedEventData : TaskEventData
    {
        public User CreatorUser { get; set; }
    }
    
    public class TaskCompletedEventData : TaskEventData
    {
        public User CompletorUser { get; set; }
    }

    在事件处理类里对事件子类进行判断即可:

    public class ActivityWriter : IEventHandler<TaskEventData>, ITransientDependency
    {
        public void HandleEvent(TaskEventData eventData)
        {
            if (eventData is TaskCreatedEventData)
            {
                //...
            }
            else if (eventData is TaskCompletedEventData)
            {
                //...
            }
        }
    }

     

    同时处理多个事件

    一个事件处理类就可以同时处理多个事件,只需要实现多个IEventHandler<T>:
    public class ActivityWriter : 
        IEventHandler<TaskCompletedEventData>, 
        IEventHandler<TaskCreatedEventData>, 
        ITransientDependency
    {
        public void HandleEvent(TaskCompletedEventData eventData)
        {
            //TODO: handle the event...
        }
    
        public void HandleEvent(TaskCreatedEventData eventData)
        {
            //TODO: handle the event...
        }
    }

     

    注册事件处理器

    自动注册
     

    建议使用自动注册,也就是什么都不用干。因为ABP会自动扫描事件处理类,在事件触发时自动使用依赖注入来取得处理器对象来处理事件,并在最后释放处理器对象。

     
    手动注册
    手动注册一般不会用到,这里就不翻译了。

     

    It is also possible to manually register to events but use it with caution. In a web application, event registration should be done at application start. It's not a good approach to register to an event in a web request since registered classes remain registered after request completion and keep re-registering for each request. This may cause problems for your application since registered class can be called multiple times. Also keep in mind that manual registration does not use dependency injection system.

    There are some overloads of register method of the event bus. The simplest one waits a delegate (or a lambda):

    EventBus.Register<TaskCompletedEventData>(eventData =>
        {
            WriteActivity("A task is completed by id = " + eventData.TaskId);
        });
    

    Thus, then a 'task completed' event occurs, this lambda method is called. Second one waits an object that implements IEventHandler<T>:

    EventBus.Register<TaskCompletedEventData>(new ActivityWriter());

    Same instance ıf ActivityWriter is called for events. This method has also a non-generic overload. Another overload accepts two generic arguments:

    EventBus.Register<TaskCompletedEventData, ActivityWriter>();

    In this time, event bus created a new ActivityWriter for each event. It calls ActivityWriter.Dispose method if it's disposable.

    Lastly, you can register a event handler factory to handle creation of handlers. A handler factory has two methods: GetHandler and ReleaseHandler. Example:

    public class ActivityWriterFactory : IEventHandlerFactory
    {
        public IEventHandler GetHandler()
        {
            return new ActivityWriter();
        }
    
        public void ReleaseHandler(IEventHandler handler)
        {
            //TODO: release/dispose the activity writer instance (handler)
        }
    }

    There is also a special factory class, the IocHandlerFactory, that can be used to use dependency injection system to create/release handlers. ASP.NET Boilerplate also uses this class in automatic registration mode. So, if you want to use dependency injection system, directly use automatic registration.

     

    取消注册

    手动注册后,可能还有手动取消注册的需求,这个也不翻译了。

    When you manually register to event bus, you may want to unregister to the event later. Simplest way of unregistering an event is disposing the return value of theRegister method. Example:

    //Register to an event...
    var registration = EventBus.Register<TaskCompletedEventData>(eventData => WriteActivity("A task is completed by id = " + eventData.TaskId) );
    
    //Unregister from event
    registration.Dispose();
    

    Surely, unregistration will be somewhere and sometime else. Keep registration object and dispose it when you want to unregister. All overloads of the Register method returns a disposable object to unregister to the event.

    EventBus also provides Unregister method. Example usage:

    //Create a handler
    var handler = new ActivityWriter();
                
    //Register to the event
    EventBus.Register<TaskCompletedEventData>(handler);
    
    //Unregister from event
    EventBus.Unregister<TaskCompletedEventData>(handler);
    

    It also provides overloads to unregister delegates and factories. Unregistering handler object must be the same object which is registered before.

    Lastly, EventBus provides a UnregisterAll<T>() method to unregister all handlers of an event and UnregisterAll() method to unregister all handlers of all events.

  • 相关阅读:
    1822. Sign of the Product of an Array
    1828. Queries on Number of Points Inside a Circle
    1480. Running Sum of 1d Array
    C++字符串
    Git&GitHb学习记录
    54. Spiral Matrix
    104. Maximum Depth of Binary Tree
    110. Balanced Binary Tree
    136. Single Number
    19、泛型入门
  • 原文地址:https://www.cnblogs.com/sagacite/p/4592807.html
Copyright © 2020-2023  润新知