C# 转发带有参数的方法

C# 转发带有参数的方法,c#,delegates,C#,Delegates,我有一个问题,我试图让一个被调用的方法将它自己的参数转发给一个类似的方法。我有一个类的实例,它可以处于任意多个不同的状态(它是针对游戏角色的,所以:空闲、行走、跑步等)。在这个类中,某些公共方法总是可以调用的,但是根据角色的状态,会采取不同的操作。这方面的一个例子是: public void TakeDamage(float damage) { // Check what state we are in, and call a function with a similiar name

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

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

我试着研究委托和操作,但是我找不到任何关于向委托和操作传递一组参数的信息。谢谢你的帮助

编辑:澄清一下,我的主要目标是使这个过程通用和可重复。因此,理想情况下,我会有一个类似的方法

CallStateMethod(string methodName, ??)

我将能够将方法名传递到,它将根据当前状态调用相应的方法,同时将任何原始参数转发到适当的状态方法。当然,由于我不确定如何做到这一点,上述方法的参数将取决于C#中可能出现的情况。如果这一点最初不清楚,很抱歉。

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

 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);
 }
Action-takeDamage;
public void SetWalk(){takeDamage=TakeWalkingDamage;}
公共财产损失(浮动损失)
{
损坏;
}
第一部分(获取方法名)非常简单,可以使用反射完成。我遇到的问题是找到一种方法将被调用方法的参数(本例中为TakeDamage)直接传递给state方法(TakeDamage\u Idle,等等)

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

var meth = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
一旦你有了它,你就可以调用它:

meth.Invoke(this, new object[]{damage});
但这其中有很多问题

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

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


另一方面,保持
if…else
链至少允许更大的内联。如果这是唯一一个不同状态影响不同事物的地方,那么您最好还是继续使用它,或者干脆将方法合并成一个,尽管在不了解更多相关逻辑的情况下,您无法真正确定。

在这种特定情况下,您正在寻找一本
字典。有时候你不需要什么花哨的东西,只需要一个简单的数据结构。反射是不好的jujuju。制作一个接口,使其损坏。创建实现接口的类。在角色类中创建它们的列表。必要时找到正确的方法并调用它。@Mephy:有没有办法用一组可变的参数来声明一个操作?例如,如果我想转发多个具有不同参数集的方法,是否可以从方法中检索参数集并将其传递到操作构造函数中,以便在运行时创建其参数集?所以,如果我通过TakeDamage(float-damage)来创建动作,但通过一些东西(float-p1,string-p2)来创建动作。@dbugger:除了性能之外还有其他原因吗?我的理解是缓存方法(就像Mephy在字典中那样)可以解决这个问题,但我不太了解反射的优缺点。我不太同意反射是“坏的jujuju”-它有它的位置,但会注意到缓存会降低更糟糕的性能影响(查找方法)但这并不是强制进入一个对象数组然后再返回所导致的。但是,虽然我不会走到“糟糕的jujuju”的地步,但它在大多数情况下并不是解决问题的最佳方式,而且这几乎肯定是其中之一。请注意:这篇文章并没有提到“我想转发的具有不同参数集的方法”。。。可能不是答案。。。如果澄清从OP指向不同的方向,我将删除。通读你的帖子,即使它没有直接解决这个问题,也非常有用,所以我不会删除,因为其他人可能需要它!旁注,
Func
float(void)
,而不是
void(float)
。。你的意思是
Action
。@Mephy确实如此。谢谢-修复了。非常感谢,将参数作为对象[]数组传递解决了我的问题。我现在确实在不同的地方使用州。每个状态都有相应的Enter\u StateName、Exit\u StateName、Update\u StateName方法。但是,看看这里的一些响应,似乎有更好的方法来实现它。我现在更确定的是,表示“状态类型”的抽象类接口
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);
}
public interface IState
{
  void TakeDamage(float damage);
  void RegainHealth(float healing);
  /* … */
}

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