看源码是一件吃力又很爽的事情,昨天还被搞的一头雾水,今天忽然守得云开见月明。明白它设计意图的同时,感觉自己又提升了一步:)
Orchard刚开始看往往毫无头绪,建议可以从Orchard.Framework&UnitTest入手,先弄明白底层框架机制,抽丝剥茧,一步一步农村包围城市。不用着急,说不定哪天睡觉一下子就理解了。
今天看一下它的事件通知模块的设计,相关类
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<StubEventBus>().As<IEventBus>(); builder.RegisterSource(new EventsRegistrationSource()); builder.RegisterType<TestClass>(); _container = builder.Build(); var c =_container.Resolve<TestClass>(); 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存储调用参数值。