• Orchard源码:EventBus&EventHandler


    概述

    看源码是一件吃力又很爽的事情,昨天还被搞的一头雾水,今天忽然守得云开见月明。明白它设计意图的同时,感觉自己又提升了一步:)

    Orchard刚开始看往往毫无头绪,建议可以从Orchard.Framework&UnitTest入手,先弄明白底层框架机制,抽丝剥茧,一步一步农村包围城市。不用着急,说不定哪天睡觉一下子就理解了。

    今天看一下它的事件通知模块的设计,相关类

    image

    1.IEventBus  事件总线接口

     public interface IEventBus : IDependency {
            IEnumerable Notify(string messageName, IDictionary<string, object> eventData);
        }

    只提供了一个Notify方法,用于事件通知。


    2.DefaultOrchardEventBus 事件总线具体实现

    相当于实现一个中转,根据messageName反射调用实现IEventHandler的方法


    3.DelegateHelper 委托辅助类

    静态类,委托方式调用方法


    4.EventsInterceptor 事件拦截器

    使用Castle.DynamicProxy作为AOP的实现


    5.EventsModule 注册事件拦截器

    系统启动时注册Events模块


    6.EventsRegistrationSource 实现Orchard动态注入总线接口

    Autofac动态依赖注入实现


    7.IEventHandler 事件处理类

    具体处理业务

    实现

    看一下它们是如何整合到一起工作的。

    1.注册相关模块

     private IContainer _container;
            private IEventBus _eventBus;
            private StubEventHandler _eventHandler;
    
            //[SetUp]
            public void Init() {
                _eventHandler = new StubEventHandler();
    
                var builder = new ContainerBuilder();
                builder.RegisterType<DefaultOrchardEventBus>().As<IEventBus>();
                builder.RegisterType<StubExceptionPolicy>().As<IExceptionPolicy>();
    
                builder.RegisterType<StubEventHandler2>()
                    .Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
                    .Named(typeof(IEventHandler).Name, typeof(IEventHandler))
                    .WithMetadata("Interfaces", typeof(StubEventHandler2).GetInterfaces().ToDictionary(i => i.Name));
                builder.RegisterInstance(_eventHandler)
                    .Named(typeof(ITestEventHandler).Name, typeof(IEventHandler))
                    .Named(typeof(IEventHandler).Name, typeof(IEventHandler))
                    .WithMetadata("Interfaces", typeof(StubEventHandler).GetInterfaces().ToDictionary(i => i.Name));
    
                _container = builder.Build();
                _eventBus = _container.Resolve<IEventBus>();
            }

    事件处理类

     public interface ITestEventHandler : IEventHandler {
                void Increment();
                void Sum(int a);
                void Sum(int a, int b);
                void Sum(int a, int b, int c);
                void Substract(int a, int b);
                void Concat(string a, string b, string c);
                IEnumerable<string> Gather(int a, string b);
                string GetString();
                int GetInt();
            }
    
            public class StubEventHandler : ITestEventHandler {
                public int Count { get; set; }
                public int Result { get; set; }
                public string Summary { get; set; }
    
                public void Increment() {
                    Count++;
                }
    
                public void Sum(int a) {
                    Result = 3 * a;
                }
    
                public void Sum(int a, int b) {
                    Result = 2 * (a + b);
                }
    
                public void Sum(int a, int b, int c) {
                    Result = a + b + c;
                }
    
                public void Substract(int a, int b) {
                    Result = a - b;
                }
    
                public void Concat(string a, string b, string c) {
                    Summary = a + b + c;
                }
    
                public IEnumerable<string> Gather(int a, string b) {
                    yield return String.Format("[{0},{1}]", a, b);
                }
    
                public string GetString() {
                    return "Foo";
                }
    
                public int GetInt() {
                    return 1;
                }
            }
            public class StubEventHandler2 : ITestEventHandler {
                public void Increment() {
                }
    
                public void Sum(int a) {
                }
    
                public void Sum(int a, int b) {
                }
    
                public void Sum(int a, int b, int c) {
                }
    
                public void Substract(int a, int b) {
                }
    
                public void Concat(string a, string b, string c) {
                }
    
                public IEnumerable<string> Gather(int a, string b) {
                    return new[] { a.ToString(), b };
                }
    
                public string GetString() {
                    return "Bar";
                }
    
                public int GetInt() {
                    return 2;
                }
            }

    2.使用(UnitTest)

    Assert.That(_eventHandler.Count, Is.EqualTo(0));
                _eventBus.Notify("ITestEventHandler.Increment", new Dictionary<string, object>());
                Assert.That(_eventHandler.Count, Is.EqualTo(1));

    Notify方法的字符串"ITestEventHandler.Increment" 就是  interface + method,DefaultOrchardEventBus接受到这个字符串分解委托调用StubEventHandler的Increment方法。

    动态注入&拦截器

    完成这个功能主要依靠 EventsRegistrationSource.cs和EventsInterceptor.cs,前者负责动态注入事件总线,后者负责拦截处理。看它的源码前最好了解下Autofac和Castle.DynamicProxy.

    最简单的示例演示

    1.注册模块

                var builder = new ContainerBuilder();
                builder.RegisterType<StubEventBus>().As<IEventBus>();
                builder.RegisterSource(new EventsRegistrationSource());
                builder.RegisterType<TestClass>();
                _container = builder.Build();

    2.相关类

     [Test]
            public void MyTest()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType&lt;StubEventBus&gt;().As&lt;IEventBus&gt;();
                builder.RegisterSource(new EventsRegistrationSource());
                builder.RegisterType&lt;TestClass&gt;();
                _container = builder.Build();
    
                var c =_container.Resolve&lt;TestClass&gt;();
                c.Invoke();
                 Assert.Fail();
             }
    
            public class TestClass {
                private readonly ICustomerEventHandler eventHandler;
                public TestClass(ICustomerEventHandler eventHandler) {
                    this.eventHandler = eventHandler;
                }
    
                public void Invoke()
                {
                    eventHandler.Changed("AAA");
                }
            }
    
            public class StubEventBus : IEventBus
            {
                public string LastMessageName { get; set; }
                public IDictionary<string, object> LastEventData { get; set; }
    
                public IEnumerable Notify(string messageName, IDictionary<string, object> eventData)
                {
    		Assert.IsTrue(eventData["str1"] == "AAA");
                    Assert.Pass();
                    return new object[0];
                }
            }
            public interface ICustomerEventHandler : IEventHandler
            {
                void Changed(string str1);
            }

    3.执行代码

     var c =_container.Resolve<TestClass>();
                c.Invoke();
                 Assert.Fail()

    原理:

    ICustomerEventHandler 没有实现类,并且也没有注册,能运行成功就是靠着EventsRegistrationSource和EventsInterceptor为它进行了动态注册和生成了代理类。

    EventsInterceptor负责拦截所有实现IEventHandler类的方法,当调用Changed方法时,拦截并且调用所有IEventBus.Notify方法,eventData存储调用参数值。

  • 相关阅读:
    ES6入门详解(二) 解构赋值
    python 入门简述
    webpack4x 简述
    ES6入门详解(一) let const
    关于HTML的简述
    按照in条件排序
    Oracle 优化效率
    input输入框校验
    <a>标签操作
    svn安装
  • 原文地址:https://www.cnblogs.com/miku/p/4297805.html
Copyright © 2020-2023  润新知