C# 获取c中函数的名称#
在Unity中,当使用协程或InvokeRepeating时,必须给出一个包含要调用的函数名的字符串。虽然如果您更改该函数的名称,这是一件痛苦的事情,因为您必须记住更改使用它的协同程序。有没有更干净的方法 现在看起来是这样的:C# 获取c中函数的名称#,c#,unity3d,C#,Unity3d,在Unity中,当使用协程或InvokeRepeating时,必须给出一个包含要调用的函数名的字符串。虽然如果您更改该函数的名称,这是一件痛苦的事情,因为您必须记住更改使用它的协同程序。有没有更干净的方法 现在看起来是这样的: InvokeRepeating ("SendChangedValues", SEND_RATE, SEND_RATE); 虽然有这样的东西会很好 InvokeRepeating (SendChangedValues.Name(), SEND_RATE, SEND_RAT
InvokeRepeating ("SendChangedValues", SEND_RATE, SEND_RATE);
虽然有这样的东西会很好
InvokeRepeating (SendChangedValues.Name(), SEND_RATE, SEND_RATE); //or
InvokeRepeating (functions.GetName(SendChangedValues), SEND_RATE, SEND_RATE);
这在c#中可能吗?或者,当我在不更改字符串的情况下更改函数名时,确保收到错误/警告
编辑1:我能想到的最干净的事情是用函数名生成一个常量字符串,并将它放在函数本身之前。所以很难忘记更改字符串,因为它就在它上面,我也只需要更改一个常量字符串就可以更改所有的协程
谢谢 我理解你的问题,我没有解决这个问题的黄金方案 可能会有帮助的是,使用lambda表达式作为一种方式来解决这个问题
它描述了一种通过传递将作为
MethodCallExpression
计算的表达式来计算方法名的方法。您可以从中提取相关信息。我记得在另一个上下文中做过类似的事情。事情是这样的:
InvokeRepeating ("SendChangedValues", SEND_RATE, SEND_RATE);
您声明了自己的方法,该方法使用原始方法:
public static void MyInvokeRepeating<T>(Func<T> method)
{
InvokeRepeating(method.Method.Name, SEND_RATE, SEND_RATE);
}
更好的是,创建一个扩展方法。在处理方法(不是属性或字段)时,不需要lambda表达式
您可以编写一个接受委托的invokereepeating
包装器。在代理上调用GetInvocationList
,以获取名为的MethodInfo
。ahhh。。如果它是下一个C#版本,您可以使用操作符的名称
现在,这对你的事业有帮助吗
private static string GetFunctionName(Action method)
{
return method.Method.Name;
}
调用时使用:
string methodName = GetFunctionName(SendChangedValues);
您可能需要探索不同的委托类型。。行动、职能等
上面提到的唯一问题是,对于每个方法签名,您可能需要定义正确的签名/重载来获取名称。如果您没有传递额外的参数,协同程序确实允许它。第一个示例显示了一个重载,其签名为Coroutine startcroutine(IEnumerator例程)代码>:
调用重复
,不幸的是,没有相同的重载。您应该能够在那里使用反射来完成它,尽管在其他一些答案中提到了这一点。您可以通过静态反射来完成这一点(至少在.NET 4中,可能在3.5及以下版本中)
//这个
InvokeRepeating(((MethodCallExpression)((Expression)(x=>x.ToString())).Body).Method.Name,SEND\u RATE,SEND\u RATE);
//与
调用重复(“ToString”,发送速率,发送速率);
您只需要知道正在调用的函数的签名,并相应地替换上例中的操作。我在我的代码库中使用以下内容,外推用于调用重复
public delegate void Task();
public static class MonoBehaviourExtensions {
public static void InvokeLater(
this MonoBehaviour b,
float time,
Task task)
{
b.Invoke(task.Method.Name, time);
}
}
像这样使用它
MyInvokeRepeating(someObject.SomeFunction);
public class MyBehaviour : MonoBehaviour {
void Start(){
this.InvokeLater(1f, DoSomething1SecondLater);
}
public void DoSomething1SecondLater(){
Debug.Log("Welcome to the future");
}
}
从现有的协同程序中创建一个enum
:
public enum MyCoroutines
{
Coroutine1,
Coroutine2
}
InvokeRepeating(MyCoroutines.Coroutine1.ToString(), x, y);
这样您就不会有拼写错误的危险,而且您可以很容易地找到并替换它们。它还非常适合播放声音和动画。以下是我对这一问题的看法,因为我最近在UnityEvent侦听器的上下文中偶然发现了这个问题,UnityEvent侦听器也存储了,只能通过方法的名称检索。我的方法在处理具有不同签名的事件处理程序时更有意义,但它也适用于任何操作和调用
public void Start()
{
援引(
methodName:GetMethodName((System.Action)分解),
时间:1f);
援引(
methodName:GetMethodName((System.Action)HandleMyNumber),
时间:2f);
}
公共静态字符串GetMethodName(System.Delegate@Delegate)
{
return@delegate.Method.Name;
}
私有空间爆炸()
{
//做一些动作,比如。。。
}
私有无效HandleMyNumber(整数)
{
//做一些动作,比如。。。
}
正如其他人之前提到的,检索MethodInfo以获取方法名称的最简单方法是通过委托类型(如Action)。我不想为每个委托类型(如Action、Action、Action)指定重载,因为我不使用这些参数。相反,我可以将任何作为参数传递的方法强制转换为正确的类型。我从未听说过这一点,但我建议您创建一个字符串变量,以便在调用中需要使用它时使用,并将此字符串保留在相应的方法旁边。您可能可以使用C#5.0引入的属性来实现这一点。它还简化了具有类似问题的INotifyPropertyChanged的实现。您可能需要将其封装在一个方法中,该方法将为您调用invokereepeating
。您可以等待c#6和nameof
操作符(请参见此),或者使用一些(不太正统的)解决方案,如expression。c#6.0应该有一个nameof
操作符来执行此操作,但现在没有帮助。此问题的答案建议新操作(FunctionName).Method.Name
。您必须指定Action
或Func
的适当通用版本。。。我认为它在重构和重载方面不会起到很好的作用。如果重命名多个重载中的一个,会更改哪个nameof
用法?至少对于方法组,之后会立即投影一些类型信息,允许解决重载问题。这比需要的要复杂得多。@BenVoigt我不确定这是否比为其他地方维护的InvokereRepeating函数编写包装更复杂。这也正是一些注释()所建议的内容,而没有将其包装到实用程序类中。@BenVoigt您是对的,
public enum MyCoroutines
{
Coroutine1,
Coroutine2
}
InvokeRepeating(MyCoroutines.Coroutine1.ToString(), x, y);
public void Start()
{
Invoke(
methodName : GetMethodName((System.Action)Explode),
time: 1f);
Invoke(
methodName : GetMethodName((System.Action<int>)HandleMyNumber),
time: 2f);
}
public static string GetMethodName(System.Delegate @delegate)
{
return @delegate.Method.Name;
}
private void Explode()
{
// Do something Action like...
}
private void HandleMyNumber(int number)
{
// Do something Action<int> like...
}