我有一个问题,我试图让一个被调用的方法将它自己的参数转发给类似的方法。我有一个类的实例可以处于任意数量的不同状态(它适用于游戏角色,因此:空闲,步行,跑步等)。在这个类中,可以始终调用某些公共方法,但根据字符的状态采取不同的操作。这方面的一个例子是:
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#中可能的内容。对不起,如果原来不清楚。
答案 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);
}