2011-08-05 11 views
5

मैं DynamicObject बनाने की कोशिश कर रहा हूं जो जेनेरिक विधि आमंत्रणों को संभालने में सक्षम है, लेकिन ऐसा लगता है कि आवश्यक API - हालांकि RC versions of 4.0 Framework में मौजूद है - आरटीएम में आंतरिक चिह्नित किया गया है (यानी CSharpInvokeMemberBinder अब आंतरिक है)। क्या इस कोड के बराबर है जो 4.0 आरटीएम में काम करेगा?मैं अपने डायनामिक ऑब्जेक्ट में जेनेरिक विधि आमंत्रण कैसे संभाल सकता हूं?

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

यद्यपि आपको उन तक पहुंच की आवश्यकता नहीं हो सकती है यदि आप अपने अग्रेषित विधि उपयोग पर डीएलआर के माध्यम से जेनरेट किए गए जेनरिक से खुश होंगे [ImpromptuInterface]: http: //code.google.com/p/impromptu-interface/wiki/UsageReallyLateBinding यह जीता जेनेरिकों के लिए काम नहीं करते जिन्हें अनुमानित नहीं किया जा सकता है लेकिन यह प्रतिबिंब से तेज़ होगा। – jbtule

+0

@jbtule मध्यम ट्रस्ट में काम करता है? –

उत्तर

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; 
    } 
संबंधित मुद्दे