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

posted @ 2015-02-23 17:16  不夜橙  阅读(709)  评论(0编辑  收藏  举报