词条 | C# dispatch |
释义 | C#方法调度 有时,我们一些做的事情,就是为了看看他们将如何工作了。 我最近有一个情况,建设系统在C#中,我想多派(双调度,尤其是),所以我张贴这证明我如何取得的希望,这将有利于他人的,或者我的系统工作其他人可以点出一个最好的解决方案,显然我在兴奋错过尝试一些我从来没有做过。 主要的问题是,我想通过创建子类逐步建立特定的事件处理能力的系统。 随着新的事件被添加到系统中,创建一个新的子类可以存储任何有关国家和实施有关的事件的处理程序。 这可以一般地被看作是一个状态机的制定,其中子类状态,所发生的事件,因为我已经叫他们,启动状态转换。 所以,我有一个参考对象在运行时这些国家之一 - 引用一个由一类是所有国家共同的祖先类 - 我要用于处理特定类型的事件定义我的一些工厂的机制。 事件对象的当前状态我想处理的是同样由一个由一类是我的所有事件的子类定义了一个共同的祖先类型的变量引用。 那么,现在的问题是,编译器,使用静态类型信息,永远只能调用基类的事件处理程序的状态。 制作这种方法将允许一个虚拟的呼叫方的运行时类型的决议,这样我可以与一个特定的重载签名的处理方法。 但是,这将意味着,我的基类需要定义每个事件类型的虚拟处理器,并且像一个大的颈部疼痛的声音。 一方面,系统不涉及超载一个虚拟方法不能做我需要在所有(自定义处理程序在调用子类中定义的没有),但是,另一方面,已经存在内置在回退功能的支持。 我想保留的基态类的处理方法将被调用的行为,如果没有更具体的处理程序由国家对象的类型实现。 双调度 我真的想在这个时候发生是有一个看起来像这样的代码行 currentState.Handle(currentEvent); 该调用最类型特定的Handle方法,可能由于该类型的currentState对象和类型的currentEvent对象。 这种行为被称为多重调度,这对比的方式是最面向对象语言的工作。 典型的方法在面向对象语言的调用语法处于一个非常特殊的句法位置的方法的参数之一:前点。 例如,调用foo.bar();查找该bar方法定义类型的foo 。 但是值得注意的是foo ,在这里,实际上是对一些参数执行bar的方法,即使它是不写的源代码的方式。 这种行为 - 单调度 - 在这种情况下是不足够的。 我要通过使用代码看起来像这样我的方法的参数: BaseState currentState; ... BaseEvent currentEvent = GetEvent(); currentState.Handle(currentEvent); 我要留言派遣到正确的方法都是基于运行时类型对currentState和currentEvent 。 重载虚函数不会让我那么远! 我需要的是双调度,和事实,即C#不提供这不应该是一个障碍。 当然,我们可以建立一个大的条件语句,看起来在参数类型,然后算出从那里做什么,但会令大家谁在方案看起来生病了。 不仅将一个报表一堆丑陋的条件是,这将意味着我们将不得不更新基类的Handle方法,我们每次添加一个事件类型。 这是疯了! 因此,这里的另一种方法。 其基本思想是,基类的Handle方法应反映在其自己的类型来寻找Handle方法,它定义。 当这个对象上,从基类派生的情况,我们会发现“超载”的子类(注意定义的方法:这不是严格来说,最重要的,但它是,直观,超载的方法名)。 我们可以看看所有的版本的Handle方法,并挑选一个需要参数的基类方法相同的该类型作为参数传递给。 如果没有匹配存在,基类可以提供一些备用的功能(也许只是提出一个错误,描述发生了什么)。 使我们得到一个简单的形式派遣多,但它确实涉及了在每个方法调用的类型反映。 幸运的是,我们可以加快,截至1位非常容易。 在一个基类的静态构造函数,我们可以反映在所有的大会(类型注意,您可以这样做,当一个程序集加载,如果你想要一个更具活力的插件体系结构),挑选出那些从我们的基地state派生类。 然后,我们可以找到所有的Handle在这些类的方法,例如他们和存储在哈希表进行检查时,将基类的Handle方法被调用。 现在,我们可以添加状态类处理某些事件,但对事件的处理没有明确的类型,调速功能,而不必更改任何代码任何地方! 在这里,我们看到从基类的静态构造函数的代码。 它认为所有大会的有关类型,缓存为每个方法的信息。 派遣= 新词典<Int64, MethodInfo>(); 的 foreach(在 Assembly.GetCallingAssembly类型吨()。GetTypes()) ( 如果(t.IsSubclassOf(typeof运算 (MyBase))) ( 的foreach(宓的 t.GetMethods的MethodInfo()) ( 如果 (ss ==“处理”) ( ParameterInfo [] = mi.GetParameters标准杆(); 如果 (pars.Length == 1) ( Int64码=((Int64)t.GetHashCode()<<32)+ 标准杆[0]。 ParameterType.GetHashCode(); dispatch.Add(代码,英里); ) ) ) ) ) 该基类的实例方法,我们希望与更多的具体行为在子类中重载就是实际发生的双调度。 / /这是一个神奇的方法,我们要根据超负荷运行时类型。 公共虚拟无效句柄( 对象O) ( Int64值=((Int64) 这一点 。GetType()。GetHashCode()<<32)+ o.GetType()。GetHashCode(); 如果 (dispatch.ContainsKey(哈希)) ( 派遣[哈希]。调用( 这一点 , 新的 对象 [](Ø)); ) 其他 ( / /这是我们的回退功能 Console.WriteLine(“处理对象”+ o.ToString()); ) ) 我试图让事情简单,你基本上可以放入任何基类的静态构造函数的代码,只是改变了该方法的名字你想调用双调度。 通过保持自己的状态类的文件,你可以保持一个高度模块化的项目,使多个开发人员可以添加从来没有甚至不必编辑同一文件的新子类的系统。 |
随便看 |
百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。