zoukankan      html  css  js  c++  java
  • [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

  • 相关阅读:
    进程线程协程
    面向对象完善总结
    面向对象编程
    常用模块2
    python常用模块
    随机验证码模块(random)
    带有key参数的函数filter,map,max,min
    python内置函数、匿名函数、递归
    python迭代器与生成器
    如何添加title左侧的图标
  • 原文地址:https://www.cnblogs.com/neverc/p/5254859.html
Copyright © 2011-2022 走看看