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存储调用参数值。

你可能感兴趣的:(EventBus)