2012-06-27 1 views
0

대리자 형식 및 대리자 형식이 Action<Object[]> 인 함수에서 작업하고 주어진 형식의 동적 함수를 만듭니다. 호출 된 경우 주어진 모든 인수를 전달합니다. 액션 핸들 :표현식 트리를 사용하여 값을 전달하는 기능이 작동하지 않습니다.

public static T GetEventDelegate<T>(Action<Object[]> handler) where T : class 
    { 
     if (!typeof(T).IsSubclassOf(typeof(Delegate))) 
      throw new Exception("T must be a delegate type"); 

     Type[] argTypes = typeof(T).GetMethod("Invoke").GetParameters().Select((para) => para.ParameterType).ToArray(); 

     List<ParameterExpression> lstArgs = new List<ParameterExpression>(
      argTypes.Select((arg)=>Expression.Parameter(arg))  
     ); 

     ParameterExpression result = Expression.Variable(typeof(Object[])); 

     var assignExpression = Expression.NewArrayInit(typeof(Object),lstArgs.ToArray()); 

     var callExpression = Expression.Call(handler.Method, result); 

     var block = Expression.Block(
      new List<ParameterExpression>(){result}, 
      new Expression[]{assignExpression,callExpression} 
     ); 

     var del = Expression.Lambda(block, lstArgs.ToArray()).Compile(); 

     return Delegate.CreateDelegate(typeof(T), del, "Invoke") as T; 
    } 

    private static void testDel() 
    { 
     var del = GetEventDelegate<EventHandler>(
      (x) => 
      { 
       //Error, because x == null 
       Debug.Print(x.ToString()); 
      } 
     ); 
     del("testString", new EventArgs()); 
    } 

는 불행하게도 액션 핸들러는 전달 된 값을 (testDel() 참조)를 가져옵니다.

오류를 찾으려면 도와주세요.

미리 감사드립니다.

답변

1

결과 ParameterExpression을 Object 유형으로 초기화 했으므로 실제로는 값을 할당하지 않았기 때문에 문제가 발생했습니다. 이 컴파일러는 (컴파일을 호출 한 후) 다음과 같이 컴파일됩니다.

실제로 할당 식을 사용하여 결과에 배열을 할당하지 마십시오.

람다를 만들 때 문제가되는 것과 관련이 없으므로 람다를 만들 때 Expression.Lambda()를 사용할 수 있습니다.

+0

당신이 옳았어요, 고맙습니다, 그게 내 문제를 해결했습니다! "Expression.Lambda"를 사용할 수 있다는 것은 무엇을 의미합니까? 언제 그것을 사용할 수 있습니까? 나는 처음에 마지막 줄 (Delegate.CreateDelegate)을 생략하려고했지만, T에 캐스팅을하지 않으면 작동하지 않았다. – muffel

+0

이것들은 마지막 두 줄이 될 수 있습니다 : 'var del = Expression.Lambda (typeof (T), block, listArgs) .Compile();' 과 'return del as T;' – JKor

+0

대단히 감사합니다 !! – muffel