C#使用方法名创建相应的委托
前言
在程序中,我们会定义各种对象和相应的方法,在创建委托的时候,我们会将相应的调用语句写死在程序里,这种硬编码调用它们的方式可读性强,但是可扩展性不高。
为了提高程序的可扩展性,这篇文章将会介绍如何在C#中仅使用方法名就能创建对应实例的委托。
步骤
使用C#的反射
在C#中,我们可以利用反射来获取程序的程序集,再通过对应方法的名称在程序集里查找相应的方法并调用。
在程序声明时使用反射:
1 | using System.Reflection; |
获取对应实例的方法
假设当前有一个游戏菜单类Hud
,内部包含AnimationTick
方法,该方法更新传入参数hudUnit
对象的动画。
1 | public class Menu : Hud { |
现在在其它的代码段中,想要获取该方法的信息,则调用Type
类型的GetMethod()
方法,获取MethodInfo
对象
1 | var hud = new Hud(); |
如果对应的对象确实存在相应的方法,则method
就会存在该方法的信息。
调用方法与创建委托
上文中的method
包含了该方法的许多信息,例如你可以通过Name
属性查询其名称。你也可以直接通过Invoke(Object object)
方法调用它(要提供实例对象)。
更加具体的信息可以查看官方文档
当然,我们的目的还是创建委托,现在,可以使用以下的语句创建之,请看CreateAnimationDelegate
方法
1 | public class Hud { |
现在,相关的委托就创建完成了,这个handleEvent
指向在hud
实例中的AnimationTick
方法,你可以调用它,或者为它绑定事件,怎么样都行。
PS:如果你的方法是静态方法,那么在CreateDelegate中,应当不填入hud
参数,因为静态方法的调用和实例对象无关
优缺点
优点
- 可扩展性好,可以仅通过方法名和实例对象定位方法。
缺点
- 性能下降,反射的运行速率低于直接调用。
- 可读性降低,代码会变得更加抽象。(应当做好注释工作。)
题外话
理论上这篇文章到这里就结束了,但是就在我实际使用的时候,我遇到了一个问题,
将得来的委托多播后(就是把几个委托调用的方法塞到一起),我想要从这个委托里删除指定名称的委托。由于委托是引用类型,所以现在仅仅知道方法名的我,要怎么从一个委托的多个方法中删除指定的方法呢?
1 | public override void RemoveEventFromHandler(string name) { |
在这段代码之前,有一个多播的MenuHandleEvent
类型委托为fired
,现在从其中删除名为name
的方法,使用GetInvocationList()
方法,获取方法列表,再比对方法名,像这样就能删除指定名称的委托啦!