2011-08-05 23 views
5

Genel yöntem çağırmalarını işleyebilen bir DynamicObject oluşturmaya çalışıyorum, ancak gerekli API - RC versions of 4.0 Framework'da bulunmasına rağmen - RTM'de dahili olarak işaretlenmiş gibi görünüyor (yani, CSharpInvokeMemberBinder artık dahili). Bu kod için 4.0 RTM'de çalışacak bir eşdeğer var mı?DynamicObject öğesindeki genel yöntem çağırmalarını nasıl ele alabilirim?

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 alınan kod)

Ben burada genel tür parametreleri almak için yansıma kullanabilirsiniz farkındayım, ama ben daha güzel bir çözüm arıyorum - eğer varsa.

+0

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

+0

Yönlendirilmiş yönteminizdeki DLR aracılığıyla çıkarılan jeneriklerden memnun kalacak olsanız da, bunlara erişmeniz gerekmeyebilir. [ImpromptuInterface]: http: //code.google.com/p/impromptu-interface/wiki/UsageReallyLateBinding kazandı Çıkarılamayan jenerikler için çalışmayın ama yansımadan daha hızlı olacaktır. – jbtule

+0

Bu jtule, Medium Trust'ta çalışıyor mu? –

cevap

0

en hızlı eşdeğer Tahmin edebiliyorum:

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; 
    } 
İlgili konular