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.

ABP的事件总线和领域事件(EventBus & Domain Events)的更多相关文章

  1. ABP理论学习之事件总线和领域事件

    返回总目录 本篇目录 事件总线 定义事件 触发事件 处理事件 句柄注册 取消注册 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以注册该事件,当某些事情发生时,可以通知到该类.这对于桌面应用 ...

  2. ABP官方文档翻译 3.7 领域事件(事件总线)

    领域事件(事件总线) 事件总线 注入IEventBus 获取默认实例 定义事件 预定义事件 处理异常 实体更改 触发事件 处理事件 处理基础事件 处理者异常 处理多个事件 注册处理者 自动 手动 取消 ...

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

    一.简要介绍 ABP vNext 封装了两种事件总线结构,第一种是 ABP vNext 自己实现的本地事件总线,这种事件总线无法跨项目发布和订阅.第二种则是分布式事件总线,ABP vNext 自己封装 ...

  4. ABP框架 - 领域事件(EventBus)

    文档目录 本节内容: EventBus 注入 IEventBus 获取默认实例 定义事件 预定义事件 处理完异常 实体修改 触发事件 处理事件 处理基类事件 处理程序异常 处理多个事件 处理程序注册 ...

  5. [Abp 源码分析]九、事件总线

    0.简介 事件总线就是订阅/发布模式的一种实现,本质上事件总线的存在是为了降低耦合而存在的. 从上图可以看到事件由发布者发布到事件总线处理器当中,然后经由事件总线处理器调用订阅者的处理方法,而发布者和 ...

  6. 浅入 ABP 系列(4):事件总线

    浅入 ABP 系列(4):事件总线 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入 ABP 系列(4):事件总线 事件总线 关于事件总线 为什么需要这 ...

  7. Android学习系列(43)--使用事件总线框架EventBus和Otto

    事件总线框架 针对事件提供统一订阅,发布以达到组件间通信的解决方案. 原理 观察者模式. EventBus和Otto 先看EventBus的官方定义: Android optimized event ...

  8. C# 事件总线 EventBus

    1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...

  9. 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)

    文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...

随机推荐

  1. angular+bootstrap+MVC 之二,模态窗

    本例实现一个bootstrap的模态窗 1.HTML代码 <!doctype html> <!--suppress ALL --> <html ng-app=" ...

  2. 【MySQL】探究之TIMESTAMP

    背景 之前有业务反馈表中start_time,end_time时间字段随着时间的推移被自动更新,这可不是业务意愿,说的严重点是要出故障的. MySQL中有DATE,DATETIME,TIMESTAMP ...

  3. 黄聪:WordPress: 使用 wp_insert_attachment 上传附件

    我们来研究一下如何在主题或者插件的开发中上传附件: 主要参考这个函数:https://codex.wordpress.org/Function_Reference/wp_insert_attachme ...

  4. DCM TUTORIAL – AN INTRODUCTION TO ORIENTATION KINEMATICS (REV 0.1)

    原英文地址:dcm_tutorial 感觉这篇文章还是很有学习价值的,所以就抽出了一些时间对本文进行的翻译.下面这个好多人用的算法就是一种DCM 滤波器. //==================== ...

  5. 去块率波 Deblocking filter

    基于块的视频编码的一个典型特点就是在图像中会出现偶发的可察觉的块结构,这是由于重构块的边缘像素与块内部像素相比恢复精度要低,块效应是目前压缩编码最明显的视觉失真之一.在H.264/ AVC视频编码标准 ...

  6. dbus

    http://blog.csdn.net/zyz511919766/article/details/7700498 http://maemo.org/maemo_training_material/m ...

  7. 在silverlight中通过WCF连接ORACLE DB数据库(转)

    转自 http://hi.baidu.com/qianlihanse/item/458aa7c8d93d4e0cac092ff4 这不是我的原创,我也是上网学习的~ How to get data f ...

  8. AngularJs 简单实现全选,多选操作

    很多时候我们在处理CURD(增删改查)的时候需要实现批量操作数据,这时候就必须使用多选操作. Angular 中实现如下(当然还有很多种比笔者写的更好的方法,这里只是简单的实现.) demo 演示地址 ...

  9. C++ 删除字符串的两种实现方式

    C++实现删除给定字符串的给定字符串思路主要有这么几种实现方式: 1.KMP算法2.用STL的string的 find,然后用erase3.用C的strstr找到字串位置,然后用strncpy写到新串 ...

  10. sqoop job 踩过的坑

    sqoop 执行可以以job形式 也可以执行用命令执行,再用sqoopjob时,踩了几个坑,分享一下 1.服务器重启 由于服务器增加硬盘,需要重启后,发现sqoop job 无法执行,报连接数据库IO ...