星空网 > 软件开发 > ASP.net

[Architect] Abp 框架原理解析 EventBus

本节目录

  • 原理介绍
  • Abp源码分析
  • 代码实现

 

原理介绍

事件总线大致原理:

(1)       在事件总线内部维护着一个事件与事件处理程序相映射的字典。

(2)       利用反射,事件总线会将实现了IEventHandler的处理程序与相应事件关联到一起,相当于实现了事件处理程序对事件的订阅。

(3)       当发布事件时,事件总线会从字典中找出相应的事件处理程序,然后利用反射去调用事件处理程序中的方法。

 

Abp源码分析

1.AbpKernelModule的Initialize方法

[Architect] Abp 框架原理解析 EventBus

 

2.EventBusInstaller的Install方法

[Architect] Abp 框架原理解析 EventBus

 

3.Kernel_ComponentRegistered

[Architect] Abp 框架原理解析 EventBus

以上将事件注册完成了.

 

剩下就需要如何触发了.

触发实际上是写在代码里的,最终调用的其实还是EventBus.Trigger()

[Architect] Abp 框架原理解析 EventBus

 

 

代码实现

看完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));        }      }    }

 

至此,事件成功执行

[Architect] Abp 框架原理解析 EventBus

 

本文地址:http://www.cnblogs.com/neverc/p/5254859.html




原标题:[Architect] Abp 框架原理解析 EventBus

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

美国海外仓信息:https://www.goluckyvip.com/tag/38260.html
美国海外仓一件代发:https://www.goluckyvip.com/tag/38261.html
美国海外仓义乌:https://www.goluckyvip.com/tag/38262.html
美国海外仓有哪些:https://www.goluckyvip.com/tag/38263.html
美国海外仓运费:https://www.goluckyvip.com/tag/38264.html
美国海外仓怎么收费:https://www.goluckyvip.com/tag/38265.html
37号文今后是否会更新?一文详解关键信息 :https://www.kjdsnews.com/a/1836441.html
探讨内地人开设香港账户的可行性 :https://www.kjdsnews.com/a/1836442.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流