2014-04-08 4 views
10

coroutines 또는 InvokeRepeating을 사용할 때 Unity에서 호출 할 함수의 이름과 함께 문자열을 제공해야합니다. 이 함수의 이름을 변경하면 고통을 느낄 수 있습니다. 왜냐하면이 함수를 사용하는 coroutine을 변경해야한다는 것을 기억해야하기 때문입니다. 이 일을하는 더 깨끗한 방법이 있습니까? 이C에서 함수명 가져 오기

InvokeRepeating (SendChangedValues.Name(), SEND_RATE, SEND_RATE); //or 
InvokeRepeating (functions.GetName(SendChangedValues), SEND_RATE, SEND_RATE); 

같은 것을 가지고 좋을 것이다하지만

InvokeRepeating ("SendChangedValues", SEND_RATE, SEND_RATE); 

C#에서이 가능 :

현재는 다음과 같습니다? 아니면 그 문자열을 변경하지 않고 함수의 이름을 변경할 때 오류/경고가 표시되는지 확인해야합니다.

편집 1 : 내가 생각할 수있는 가장 깨끗한 것은 함수의 이름으로 const 문자열을 만들고 함수 자체 앞에 놓는 것입니다. 따라서 문자열을 변경하는 것을 잊어 버리는 것이 더 어렵습니다. 문자열 바로 위에 있으므로 문자열을 변경하여 모든 coroutine을 변경하면됩니다.

감사합니다.

+2

아이브는 들어 본 적이 없지만 호출 할 때 사용할 문자열 변수를 만들고 해당 문자열을 해당 메서드 옆에 유지해야한다고 제안합니다. – Sayse

+0

하하, 예, 그게 제가 생각한 것입니다 : 당신의 코멘트를 쓰는 동안 DI가 내 질문을 편집하고있는 것 같습니다 : P –

+0

함수를 장식하는 사용자 정의 속성을 만들 수 있습니다.이 속성은 함수 이름이 바뀌면 변경하지 않아도되는 식별자로 문자열을 취할 수 있습니다. 그런 다음 해당 문자열을 제공하는 코드를 사용하여 해당 문자열로 초기화 된 사용자 지정 특성으로 장식 된 함수를 찾고 메서드 이름을 가져 와서 매개 변수로 'InvokeRepeating'에 전달합니다.누군가가 속성의 문자열을 변경하는 경우를 보장하지는 않지만, 그렇게 할 필요가 없어서 이론적으로 (적어도 이론상으로) 빈약 한 코드 리팩터의 기회를 줄여야합니다. – LB2

답변

9

아 .. 만약 다음 C# 버전이라면 이라는 이름의 연산자를 사용할 수 있습니다.

지금은 도움이 될까요?

string methodName = GetFunctionName(SendChangedValues); 
서로 다른 대리인 유형을 탐색 할 수 있습니다

.. 액션, Func을 등 :

private static string GetFunctionName(Action method) 
{ 
return method.Method.Name; 
} 

를 사용하여 호출

위의 유일한 문제는 모든 메소드 서명에 대해 올바른 서명/오버로드를 정의하여 이름을 가져와야한다는 것입니다.

+0

위대한 작품입니다. 매개 변수가있는 함수의 경우'string GetName (동작 메서드)'이 있지만 괜찮습니다. 비록 내가 이것을 호출 할 때 변수의 타입을 추가해야만한다 :'Helpers.GetName (MethodWithStringParam)'. 이 문제를 해결할 방법이 있는지 궁금 해서요. 그래서 그냥'Helpers.GetName (MethodWithStringParam)'할 수 있습니다. 그것은 좋은 입찰가 거래는 아니지만. 감사! –

2

귀하의 문제를 이해하고 이에 대한 황금의 해결책이 없습니다.

blog post과 같이 람다 식을 사용하는 것이 도움이 될 수 있습니다.

으로 평가 될 Expression을 전달하여 메서드 이름을 찾는 방법을 설명합니다. 거기에서 관련 정보를 추출 할 수 있습니다.

2

다른 컨텍스트에서 비슷한 것을 한 것을 기억합니다. 그것은이 같은 갔다 : 당신은 당신의 자신의 방법을 선언

을, 즉 원래의 방법을 사용하여 다음

public static void MyInvokeRepeating<T>(Func<T> method) 
{ 
    InvokeRepeating(method.Method.Name, SEND_RATE, SEND_RATE); 
} 

및 더 나은 아직이

MyInvokeRepeating(someObject.SomeFunction); 

처럼 메소드를 호출을을 확장 방법.

1

메서드 (속성 또는 필드 제외)를 처리 할 때 람다식이 필요하지 않습니다.

델리게이트를 사용하는 InvokeRepeating 래퍼를 작성할 수 있습니다. 위임자의 GetInvocationList으로 전화하여 MethodInfo이라는 이름을 가져옵니다.

3

코 루틴은 허용합니다 IF 추가 매개 변수를 전달하지 않습니다.

using UnityEngine; 
using System.Collections; 

public class Example : MonoBehaviour { 
    void Start() { 
     print("Starting " + Time.time); 
     StartCoroutine(WaitAndPrint(2.0F)); 
     print("Before WaitAndPrint Finishes " + Time.time); 
    } 
    IEnumerator WaitAndPrint(float waitTime) { 
     yield return new WaitForSeconds(waitTime); 
     print("WaitAndPrint " + Time.time); 
    } 
} 

InvokeRepeating은 불행하게도 이와 같은 과부하가없는 : 첫 번째 예는 in the documentationCoroutine StartCoroutine(IEnumerator routine);의 서명 과부하를 나타낸다. 다른 답변에서 언급했듯이 리플렉션을 사용하여이 작업을 수행 할 수 있어야합니다.

2

당신은 당신은 당신이 호출하고있는 함수의 서명을 알 필요가

// This 
InvokeRepeating(((MethodCallExpression)((Expression<Action<string>>)(x => x.ToString())).Body).Method.Name, SEND_RATE, SEND_RATE); 

// Is the same as 
InvokeRepeating("ToString", SEND_RATE, SEND_RATE); 

(적어도 .NET 4 아래 아마도 3.5)을 정적 반사를 통해이 작업을 수행하고 작업을 대체 할 수 위의 예에서.

+0

그건 필요 이상으로 복잡해. –

+0

@BenVoigt 다른 곳에서 유지 관리되는 InvokeRepeating 함수에 래퍼를 작성하는 것보다 더 복잡하다는 데 동의하지 않습니다. 또한 Utility 클래스에서 래핑하지 않고 몇 가지 주석 (http://joelabrahamsson.com/getting-property-and-method-names-using-static-reflection-in-c/)에 의해 제안 된 내용을 정확하게 설명합니다. – Michael

+0

pmcoltrane 님의 의견에 비평 ... –

4

내 코드베이스에서 다음을 사용하여 invokerepeating을 추정합니다.

public enum MyCoroutines 
{ 
Coroutine1, 
Coroutine2 
} 

InvokeRepeating(MyCoroutines.Coroutine1.ToString(), x, y); 

당신이 맞춤법의 위험을 함수 이름이 없습니다 플러스 당신이 찾을 수있는이 방법을 :

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); 
    } 
} 

은 당신이 가지고있는 코 루틴 밖으로 enum 확인이

public class MyBehaviour : MonoBehaviour { 
    void Start(){ 
    this.InvokeLater(1f, DoSomething1SecondLater); 
    } 

    public void DoSomething1SecondLater(){ 
    Debug.Log("Welcome to the future"); 
    } 
} 
2

처럼 사용 쉽게 교체 할 수 있습니다. 소리와 애니메이션을 재생할 때도 좋습니다.

0

이 문제는 최근에 UnityEvent 청취자의 컨텍스트에서 발견 되었기 때문에이 문제를 해결했습니다.이 청취자는 메서드 이름을 통해서만 검색 할 수 있습니다. 내 접근 방식은 서로 다른 서명으로 이벤트 처리기를 처리 할 때 더 유용하지만 어떤 경우에도 을 호출합니다.을 호출 할 수도 있습니다. 다른 사람이 전에 언급했듯이

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... 
} 

, 메서드의 이름을 얻기 위해 MethodInfo를 검색하는 간단한 방법은 대리자 형식과 같은 액션를 통해입니다. 액션, 액션, 액션과 같은 모든 위임 유형에 오버로드를 지정하고 싶지는 않습니다. 왜냐하면이 매개 변수를 사용하지 않기 때문입니다. 대신 매개 변수로 전달할 모든 메서드를 올바른 형식으로 캐스팅 할 수 있습니다.