2011-03-22 5 views
8

대리인을 MethodInfo로 할 수있는 것처럼 개체에 바인딩하지 않고 저장하는 방법이 있습니까? 지금은 MethodInfo를 저장하므로 메소드를 호출 할 객체를 제공 할 수 있습니다. 그러나 나는 오히려 그것을 대의원으로 생각해야한다. 첫 번째 매개 변수가 "this"라는 것을 .net에 알려주는 속성이 있습니까?C# 대리자가 인스턴스에 바인딩되지 않았습니까?

MethodInfo mi; 
Action<string> func; 
mi.Invoke(this,new object[]{str}); 
func(this, str); //Is this possible with a delegate? 
+0

당신이 좀 더 세부 질문을 바꿔 수, 나는 내가 부분적으로하지만 그것을 가지고 생각할 수 없습니다 확실한. –

+0

무슨 뜻인지 예를 추가했습니다. 기본적으로 객체 참조가없는 델리게이트를 호출하여 호출 할 때 객체를 제공 할 수 있습니까? – Will

+1

질문의 제목을 명확하게하기 위해 제목을 변경했습니다. 마음에 들지 않으면 다시 굴러 라.) –

답변

11

원하는 것을 open instance delegate이라고합니다. C# 언어에서는 직접 지원되지 않지만 CLR에서는 지원합니다.

기본적으로 열려있는 인스턴스 대리인은 일반 대리인과 동일하지만 일반 매개 변수보다 앞에 this에 대한 추가 매개 변수가 필요하며 null 메서드 (예 : 정적 메서드의 대리자)가 있습니다. 예를 들어, Action<T>의 오픈 인스턴스 동등한은 다음과 같습니다

delegate void OpenAction<TThis, T>(TThis @this, T arg); 

다음은 완전한 예입니다 :
void Main() 
{ 
    MethodInfo sayHelloMethod = typeof(Person).GetMethod("SayHello"); 
    OpenAction<Person, string> action = 
     (OpenAction<Person, string>) 
      Delegate.CreateDelegate(
       typeof(OpenAction<Person, string>), 
       null, 
       sayHelloMethod); 

    Person joe = new Person { Name = "Joe" }; 
    action(joe, "Jack"); // Prints "Hello Jack, my name is Joe" 
} 

delegate void OpenAction<TThis, T>(TThis @this, T arg); 

class Person 
{ 
    public string Name { get; set; } 

    public void SayHello(string name) 
    { 
     Console.WriteLine ("Hi {0}, my name is {1}", name, this.Name); 
    } 
} 

은 자세한 내용은 this article에서보세요.

+0

C#이 직접 지원하지 않는다는 단점이 있습니다. 정보 주셔서 감사 : D 조. – Will

5

당신은 MethodInfo에 대한 강력한 형식의 대리자를 만들 수 Delegate.CreateDelegate 방법을 사용할 수 있습니다. 당신이 컴파일시에 메소드의 서명을 알 수없는 경우

, 당신은 Func<...> 사용하여 반사를 만들거나 MethodInfo 호출하는 람다 식 만들 수 있습니다 (이것은 태닝라고 함)

MethodInfo methodInfo = ...; 
object thisObj = ...; 
Func<object[]> callMethod = args => methodInfo.Invoke(thisObj, args); 

Delegate.CreateDelegate과 달리 대리인이 호출 될 때마다 여전히 성능에 영향을 미칩니다.

+0

람다를 사용하여 더 좋게 생각하지 않았습니다. 감사합니다. – Will

0

델리게이트는 본질적으로 단지 MethodInfo (실제로는 MethodBase)이며 성능을위한 내부 포인터가있는 개체 참조입니다. 따라서 MethodInfo이 있으면 본질적으로 언 바운드 대리인이 있습니다. 특정 유스 케이스는 무엇입니까?

+1

기능적으로 네, 대략 같습니다. 그러나 MethodInfo.Invoke는 델리게이트 호출보다 훨씬 느립니다. –

+0

@Thomas Levesque : Granted. 반복 호출의 경우, Delegate를 호출하여 성능을 향상시킬 수 있습니다.CreateDelegate()'를 사용하여 바인드 된 델리게이트를 만들었지 만 bind-call-discard, bind-call-discard 패턴에 대해서는 성능상의 이점을 제공하지 못합니다. –

0

이유는 단순히

Action<T, string> unbound = (This, str) => This.Method(str); 

그래서 당신은

unbound(instanceA, "hello"); 
unbound(instanceB, "world"); 

또는

Action<string> bound = str => unbound(instanceC, str); 
관련 문제