2011-08-05 5 views
5

일반 메서드 호출을 처리 할 수있는 DynamicObject을 만들려고하지만, 필요한 API가 RC versions of 4.0 Framework에 있지만 RTM에서 내부로 표시되어 있습니다 (즉, CSharpInvokeMemberBinder은 현재 내부적 임). 4.0 RTM에서 작동하는이 코드에 해당하는 것이 있습니까?내 DynamicObject에서 일반 메서드 호출을 처리하려면 어떻게해야합니까?

public class TransparentObject<T> : DynamicObject { 
    private readonly T target; 

    public TransparentObject(T target) { 
     this.target = target; 
    } 

    public override bool TryInvokeMember(
     InvokeMemberBinder binder, object[] args, out object result) { 
     var csBinder = binder as CSharpInvokeMemberBinder; 
     var method = typeof(T).GetMethod(binder.Name, BindingFlags.Public 
      | BindingFlags.NonPublic | BindingFlags.Instance); 
     if (method == null) 
      throw new MissingMemberException(string.Format(
       "Method '{0}' not found for type '{1}'", binder.Name, typeof(T))); 
     if (csBinder.TypeArguments.Count > 0) 
      method = method.MakeGenericMethod(csBinder.TypeArguments.ToArray()); 
     result = method.Invoke(target, args); 
     return true; 
    } 
} 

(http://bugsquash.blogspot.com/2009/05/testing-private-methods-with-c-40.html에서 가져온 코드)

내가 여기에 제네릭 형식 매개 변수를 얻기 위해 반사를 사용할 수 있다는 것을 알고,하지만 난 더 좋은 솔루션을 찾고 있어요 -가있는 경우.

+0

속는 http://stackoverflow.com/questions/5492373/get-generic-type-of-call-to-method-in-dynamic-object – jbtule

+0

전달 방법의 DLR을 통해 추측 한 제네릭에 만족할 수 있으면 액세스 할 필요는 없지만 [ImpromptuInterface]를 사용하십시오. http : //code.google.com/p/impromptu-interface/wiki/UsageReallyLateBinding 유추 할 수없는 제네릭에 대해서는 작동하지 않지만 리플렉션보다 빠릅니다. – jbtule

+0

@jbtule은 Medium Trust에서 작동합니까? –

답변

0

가장 빠른 동등한 것 같아요 수 있습니다

private static readonly Func<InvokeMemberBinder, IList<Type>> GetTypeArguments; 

    static TransparentObject() 
    { 
     var type = typeof(RuntimeBinderException).Assembly.GetTypes().Where(x => x.FullName == "Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder").Single(); 
     var dynamicMethod = new DynamicMethod("@", typeof(IList<Type>), new[] { typeof(InvokeMemberBinder) }, true); 
     var il = dynamicMethod.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Castclass, type); 
     il.Emit(OpCodes.Call, type.GetProperty("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder.TypeArguments", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true)); 
     il.Emit(OpCodes.Ret); 
     GetTypeArguments = (Func<InvokeMemberBinder, IList<Type>>)dynamicMethod.CreateDelegate(typeof(Func<InvokeMemberBinder, IList<Type>>)); 
    } 

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 
    { 
     var method = typeof(T).GetMethod(binder.Name, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance); 
     if (method == null) throw new MissingMemberException(string.Format("Method '{0}' not found for type '{1}'", binder.Name, typeof(T))); 
     var typeArguments = GetTypeArguments(binder); 
     if (typeArguments.Count > 0) method = method.MakeGenericMethod(typeArguments.ToArray()); 
     result = method.Invoke(target, args); 
     return true; 
    } 
관련 문제