Welcome

首页 / 软件开发 / C# / C#及.NET中从控制反转(依赖注入)想到事件注入 (非AOP)

C#及.NET中从控制反转(依赖注入)想到事件注入 (非AOP)2014-10-05 cnblogs 熬夜的虫子概要

所谓事件注入是我一时兴起随便杜撰的词,其思想借鉴依赖注入。当然看到这个词很多同学会想到AOP,这里先不置可否。

依赖注入(Dependency Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

也就是说依赖注入在我们的项目场景中充当一个解耦的角色。在项目结构中它可以解耦出一个模块、一个服务。T2噬菌体同学在他的博文中描述了一个游戏打怪的例子来解释依赖注入的作用。那么我们同样用打怪的例子来阐述下事件注入的场景。

详解

关于原型的设计可以参考T2同学对游戏打怪的描述,我这里直接略过看效果图

下面我们撇开T2同学对依赖注入场景的设计。假设目前这个demo就是可行的。但是随着游戏版本的更新,招式越来越多,效果越来越绚,规则越来越多。T2同学用依赖注入解决的重点是将Role和武器之间的依赖,封装算法簇,让它们之间可以互相替换,让算法的变化独立于使用算法的客户类。

那么浮现问题点,如果我要更新的并不是武器等因素,而是对流程的更新。例如玩dota的同学都知道,一个英雄他的技能前后摇摆的时间也是很重要的因素,好吧,我们给游戏添加技能前摇的设置,砍完怪的我还得获得金币,嗯,再添加一下攻击后获得金币的内容。如何符合我们的OCP原则呢。于是,我们引入事件注入的概念。

首先我们来定义我们所需要的行为

/// <summary> /// 攻击前事件 /// </summary> public static event EventHandler<EventArgs> BeforeAttackEvent;protected virtual void BeforeAttack(EventArgs e) { EventHandler<EventArgs> tmp = BeforeAttackEvent; if (tmp != null) tmp(this, e); }/// <summary> /// 攻击后事件 /// </summary> public static event EventHandler<GameEventArgs> AttackedEvent;protected virtual void OnAttacked(GameEventArgs e) { EventHandler<GameEventArgs> tmp = AttackedEvent; if (tmp != null) tmp(this, e); }
这里定义的仅仅是事件的句柄,如果在这里就实现我们事件的实体也就违背了我们ocp的原则以及事件注入的概念。

这里要提出说明的EventArgs 是包含事件数据的类的基类,如果说我们需要对注入的事件进行额外的信息处理,例如我需要获得金币,那么金币这个属性需要在事件数据中说明

例如上述的攻击后事件

/// <summary>/// 注入事件元素/// </summary>public class GameEventArgs :EventArgs{public GameEventArgs(): this(0){} public int Coin{get;set;} public GameEventArgs(int coin){Coin = coin;}}