转发带参数的方法

时间:2014-12-21 00:04:01

标签: c# delegates

我有一个问题,我试图让一个被调用的方法将它自己的参数转发给类似的方法。我有一个类的实例可以处于任意数量的不同状态(它适用于游戏角色,因此:空闲,步行,跑步等)。在这个类中,可以始终调用某些公共方法,但根据字符的状态采取不同的操作。这方面的一个例子是:

public void TakeDamage(float damage)
{
    // Check what state we are in, and call a function with a similiar name

    if (state == idle)
    {
        TakeDamage_Idle(damage);
    } 
    else if (state == walk)
    {
        TakeDamage_Walk(damage);
    }
    ...and so on
}

private void TakeDamage_Idle(float damage)
{
    // Do something
}

private void TakeDamage_Walk(float damage)
{
    // Do something different
}

(以上是部分伪代码)。我想要做的是自动化上面的过程。我需要能够检索我想要调用的方法的名称(这取决于状态),然后在传入任何参数的同时调用它。第一部分(获取方法名称)很简单,可以使用Reflection完成。我遇到的问题是找到一种方法将被调用方法的参数(在本例中为TakeDamage)直接传递给state方法(TakeDamage_Idle等)。显然它可以像上面那样手动完成,但我希望这个过程是通用的,这样我就可以将它应用到我想要的任何方法上。

我已经尝试过查看委托和操作,但我找不到任何关于将一组参数传递给它们的信息。谢谢你的帮助。

编辑:为了澄清,我的主要目标是使这个过程具有通用性和可重复性。理想情况下,我会有像

这样的方法
CallStateMethod(string methodName, ??)

我可以将方法名称传入,并根据当前状态调用正确的相应方法,并将任何原始参数转发到正确的状态方法。当然,因为我不知道如何做到这一点,上述方法的参数将取决于C#中可能的内容。对不起,如果原来不清楚。

2 个答案:

答案 0 :(得分:2)

  

第一部分(获取方法名称)很简单,可以使用Reflection完成。我遇到的问题是找到一种方法将被调用方法的参数(在本例中为TakeDamage)直接传递给状态方法(TakeDamage_Idle等)。

好的,你有名字,所以你得到MethodInfo

var meth = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

完成后,您可以Invoke

meth.Invoke(this, new object[]{damage});

但这不仅仅是一些问题。

如果您真的有这么多可能的方法,很难在if - else分支中跟踪它们,那么就创建一个字典(我假设state是带常量的整数,但以下内容适用于enum和其他类型:

Dictionary<int, Action<float>> actions = new Dictionary<int, Action<float>>();
actions[idle] = TakeDamage_Idle;
actions[walk] = TakeDamage_Walk;
…

public void TakeDamage(float damage)
{
  actions[state](damage);
}

实际上,虽然这种模式有时很有用,但它不太可能是最好的方法。

如果各种&#34;状态&#34;在这里做出如此大的不同,他们在其他地方也不会有所作为吗?如果是这样,那么你自己制作这种类型可能会好得多:

public interface IState
{
  void TakeDamage(float damage);
  void RegainHealth(float healing);
  /* … */
}

public class WalkingState : IState
{
  /* implement here */
}

然后你可以在状态之间移动(这也提供了很大的灵活性,能够参数化状态和使用有关步行的参数,这些参数在空闲时没有意义,等等。)

另一方面,保持if…else链至少可以实现更大的内联。如果这是不同状态影响不同事物的唯一地方,那么你可能最好不要继续使用它,或者甚至只是将方法整合到一个方面,尽管如果不知道更多关于所涉及的逻辑。

答案 1 :(得分:1)

标准OOP解决方案是创建处理“state”操作的类,并为当前状态调用相应的方法:

 interface IState
 {
      void TakeDamage(float);
      ....
 }

 class WalkingState : IState
 {
      ActiveObject parent;
      public WalkingState(ActiveObject parent) { this.parent = parent;}
      public void TakeDamage(float) 
      {
          // do whatever needed including calling parent.XXX methods  
          ....
      }
      ...
 }

 class ActiveObject
 { 
     IState currentState;

     public void SetWalk () { currentState = new WalkState(this);}

     public TakeDamage(float damage)
     {
        currentState.TakeDamage(damage);
     }
     ...
 }

如果对于多种类型的对象(例如士兵,企鹅,鸟类的“步行状态”)应该或多或少地统一处理更多动作,这将很好地工作。

或者,如果您只有一两个需要转发的方法,您可以拥有单个代理:

 Action<float> takeDamage;

 public void SetWalk () { takeDamage = TakeWalkingDamage;}

 public void TakeDamage(float damage)
 {
    takeDamage(damage);
 }