[Architect] Abp 框架原理解析(2) EventBus
本节目录
原理介绍
事件总线大致原理:
(1) 在事件总线内部维护着一个事件与事件处理程序相映射的字典。
(2) 利用反射,事件总线会将实现了IEventHandler的处理程序与相应事件关联到一起,相当于实现了事件处理程序对事件的订阅。
(3) 当发布事件时,事件总线会从字典中找出相应的事件处理程序,然后利用反射去调用事件处理程序中的方法。
Abp源码分析
1.AbpKernelModule的Initialize方法

2.EventBusInstaller的Install方法

3.Kernel_ComponentRegistered

以上将事件注册完成了.
剩下就需要如何触发了.
触发实际上是写在代码里的,最终调用的其实还是EventBus.Trigger()

代码实现
看完Abp的实现,关键点还是反射以及IoC注册对象事件的拦截.
先上实现效果:
interface IPerson
{
void Say();
}
class Person : IPerson
{
public IEventBus EventBus { get; set; }
public void Say()
{
var str = "Say";
Console.WriteLine(str);
EventBus.Trigger(typeof(SayEventData), this, new SayEventData() { Content = str });
}
}
定义上面需要的EventData,实际这是事件基类.
[Serializable]
public abstract class EventData : IEventData
{
public DateTime EventTime { get; set; } /// <summary>
/// The object which triggers the event (optional).
/// </summary>
public object EventSource { get; set; } protected EventData()
{
EventTime = DateTime.Now;
}
} public interface IEventData
{
DateTime EventTime { get; set; } object EventSource { get; set; }
}
自定义事件,继承事件基类,可以添加事件需要传递的数据.
public class SayEventData : EventData
{
public string Content { get; set; }
}
定义IEventHandle,实际这是事件处理程序,一个事件一般对应多个事件处理程序.
public interface IEventHandler
{ }
public interface IEventHandler<in TEventData> : IEventHandler
{
/// <summary>
/// Handler handles the event by implementing this method.
/// </summary>
/// <param name="eventData">Event data</param>
void HandleEvent(TEventData eventData);
}
自定义的EventHandle,各种事件订阅器.
public class SayEvent : IEventHandler<SayEventData>
{
public void HandleEvent(SayEventData eventData)
{
Console.WriteLine("进入事件啦:" + eventData.Content);
}
}
事件总线EventBus,管理事件的中心.可以细化接口.
public interface IEventBus
{
void Register(Type eventType, IEventHandler handler); void Trigger(Type eventType, object eventSource, IEventData eventData);
}
EventBus实现,核心是反射调用事件处理程序.
public class EventBus : IEventBus
{
public static EventBus Default { get { return DefaultInstance; } }
private static readonly EventBus DefaultInstance = new EventBus();
private readonly Dictionary<Type, List<IEventHandler>> _eventHandlers;
public EventBus()
{
_eventHandlers = new Dictionary<Type, List<IEventHandler>>();
}
public void Register(Type eventType, IEventHandler handler)
{
GetOrCreateHandlerFactories(eventType).Add(handler);
}
private List<IEventHandler> GetOrCreateHandlerFactories(Type eventType)
{
List<IEventHandler> handlers;
if (!_eventHandlers.TryGetValue(eventType, out handlers))
{
_eventHandlers[eventType] = handlers = new List<IEventHandler>();
}
return handlers;
}
public void Trigger(Type eventType, object eventSource, IEventData eventData)
{
eventData.EventSource = eventSource;
var handles = GetOrCreateHandlerFactories(eventType);
if (handles.Count > 0)
{
foreach (var eventHandler in handles)
{
if (eventHandler == null)
{
throw new Exception("Registered event handler for event type " + eventType.Name + " does not implement IEventHandler<" + eventType.Name + "> interface!");
}
//eventHandler.
var handlerType = typeof(IEventHandler<>).MakeGenericType(eventType); handlerType
.GetMethod("HandleEvent", BindingFlags.Public | BindingFlags.Instance, null, new[] { eventType }, null)
.Invoke(eventHandler, new object[] { eventData });
}
}
}
}
执行,来测试是否通了.
private static IEventBus _eventBus;
static void Main(string[] args)
{
var container = IocManager.Instance.IocContainer;
container.Register(Component.For<IEventBus>().Instance(EventBus.Default));
_eventBus = container.Resolve<IEventBus>();
container.Kernel.ComponentRegistered += Kernel_ComponentRegistered; //在Abp中,由于注册了所有ITransientDependency,所以这2个不需要手动注册
container.Register(Component.For<Person, IPerson>());
container.Register(Component.For<IEventHandler<SayEventData>, SayEvent>()); container.Resolve<IPerson>().Say();
Console.ReadKey();
}
注册事件的绑定
private static 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], handler.ComponentModel.Implementation.CreateInstance<IEventHandler>());
_eventBus.Register(genericArgs[0], (IEventHandler)IocManager.Instance.IocContainer.Resolve(handler.ComponentModel.Implementation));
}
}
}
至此,事件成功执行

本文地址:http://www.cnblogs.com/neverc/p/5254859.html
[Architect] Abp 框架原理解析(2) EventBus的更多相关文章
- [Architect] Abp 框架原理解析(5) UnitOfWork
本节目录 介绍 分析Abp源码 实现UOW 介绍 UOW(全称UnitOfWork)是指工作单元. 在Abp中,工作单元对于仓储和应用服务方法默认开启.并在一次请求中,共享同一个工作单元. 同时在Ab ...
- [Architect] Abp 框架原理解析(4) Validation
本节目录 介绍 DataAnnotations ICustomValidate IShouldNormalize 实现Abp Validation 介绍 Abp中在Application层集成了val ...
- [Architect] Abp 框架原理解析(3) DynamicFilters
本节目录 介绍 定义Filter 设置Filter 这是Abp中多租户.软删除.激活\禁用等如此方便的原因 Install-Package EntityFramework.DynamicFilters ...
- [Architect] Abp 框架原理解析(1) Module
本节目录 Abp介绍 Abp源码分析 代码实现 Abp介绍 学习了一段时间的Abp,领略了一下前辈的架构.总结还是SOLID,降低耦合性. 虽然从架构上说甚至不依赖于DI框架,但实际上在基础框架中还是 ...
- EventBus框架原理解析(结合源代码)(上)
上一篇文章http://blog.csdn.net/crazy__chen/article/details/47425779 和大家一起模仿EventBus的实现机制.和大家一起写出了一个简易的Eve ...
- ABP架构解析
ABP总体介绍 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- andorid jar/库源码解析之EventBus
目录:andorid jar/库源码解析 EventBus: 作用: 用于不同Activity,Service等之间传递消息(数据). 栗子: A页面:onCreate定义 EventBus.ge ...
- [EventBus源码解析] 初探EventBus
本期blog作为EventBus(以下简称EB)学习的始动篇,主要记载了EB的功能.优点.使用方法,内容基于github上的README.md与HOWTO.md. 何为EventBus EB实现了An ...
- [Architect] ABP(现代ASP.NET样板开发框架) 翻译
所有翻译文档,将上传word文档至GitHub 本节目录: 简介 代码示例 支持的功能 GitHub 简介 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目) ...
随机推荐
- 搭建自己的OpenWrt开发环境
1. 安装环境Linux系统,如果在CentOS上操作,需安装如下依赖包:yum install binutils bzip2 gawk gcc gcc-c++ gettext makencurse ...
- C#转C++的一点分享
前几天看到这样一篇博客<那些年·我们读过的专业书籍>,里面列了很多大家认为很好的书,加上自己在自学C++的工程中也看了不少书,感觉并不是所有的书都值得花时间去看的,毕竟很多人一年下来也看不 ...
- Windows下Nginx的安装与配置(转)
一.首先去官网下载 nginx1.0.11的Windows版本,官网下载:http://nginx.org/download/nginx-1.0.11.zip 下载到软件包后,解压 nginx-ngi ...
- THEOS makefile
转自https://www.h4ck.org.cn/2013/07/theos-makefile/ theos的makefile写法与其他linux/unix环境下的makefile写法大同小异,但是 ...
- nodejs express 框架解密3-中间件模块
本文档是基于express 3.4.6 的 在上篇中我们提到了中间件,这篇主要解释这个模块,middleware.js 为: var utils = require('./utils'); /** * ...
- iOS中生成并导入基于Swift编程语言的Framework
从iOS 8.0开始就引入了framework打包方式以及Swift编程语言.我们可以主要利用Swift编程语言将自己的代码打包成framework.不过当前Xcode 7.x在自动导入framewo ...
- C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现[转载]
原文:http://outofmemory.cn/code-snippet/35524/AES-with-javascript-java-csharp-python-or-php c#里面的AES加密 ...
- 実行時にMicrosoft.ACE.OLEDB.12.0プロバイダーはローカルコンピュータに登録されていませんが出てしまう
環境 Windows8 64bit Visual Studio 2010 Access 2010 32bit 接続プロバイダは「Microsoft.ACE.OLEDB.12.0」 対応 Downloa ...
- openssl 学习之从证书中提取RSA公钥N 和 E
原文链接: http://blog.csdn.net/kkxgx/article/details/19850509 通常数字证书包含很多信息,其中N和E值即我们称为的公钥.如何从PEM 或者DER格式 ...
- fflua更新-增加对引用的支持
简介: fflua 发布了有段时间了,很多网友都用了,并且提供了一些很好的反馈.其中一个就是c++接口注册到lua中时,对引用的支持.这样使用起来更加方便. 原有方式: fflua 中注册c++的类用 ...