2009-07-14 19 views
32

googling और इतने पर लैंडिंग और होने के बाद पढ़ा this other questionMethodInfo से एक प्रतिनिधि बनाता है?

यह एक MethodInfo से एक सही प्रतिनिधि का निर्माण करने के यदि आप नंबर या संकलन समय पर मापदंडों के प्रकार नहीं पता था कि संभव है?

अधिक इस पर: इस Reflection.Emit या प्रकार बिल्डरों के उपयोग के बिना सुंदर ढंग से किया जा सकता है?

यह sorta मेरे लिए एक बहुत बेकार है क्योंकि Delegate.CreateDelegate मुझे आवश्यकता है पहले पैरामीटर के रूप सही प्रतिनिधि प्रकार निर्दिष्ट करने वरना यह अपवाद फेंक या एक गलत विधि आह्वान होता है।

मैं कुछ निंजा गियर बना रहा हूं और इससे बहुत मदद मिलेगी ... धन्यवाद!

/// <summary> 
/// Builds a Delegate instance from the supplied MethodInfo object and a target to invoke against. 
/// </summary> 
public static Delegate ToDelegate(MethodInfo mi, object target) 
{ 
    if (mi == null) throw new ArgumentNullException("mi"); 

    Type delegateType; 

    var typeArgs = mi.GetParameters() 
     .Select(p => p.ParameterType) 
     .ToList(); 

    // builds a delegate type 
    if (mi.ReturnType == typeof(void)) { 
     delegateType = Expression.GetActionType(typeArgs.ToArray()); 

    } else { 
     typeArgs.Add(mi.ReturnType); 
     delegateType = Expression.GetFuncType(typeArgs.ToArray()); 
    } 

    // creates a binded delegate if target is supplied 
    var result = (target == null) 
     ? Delegate.CreateDelegate(delegateType, mi) 
     : Delegate.CreateDelegate(delegateType, target, mi); 

    return result; 
} 

नोट:: मैं एक Silverlight आवेदन के निर्माण कर रहा हूँ कि जिसमें मैं कई है एक निर्मित साल पहले जावास्क्रिप्ट आवेदन की जगह लेंगे


यहाँ एक सामान्य समाधान है जावास्क्रिप्ट इंटरफेस जो एक ही सिल्वरलाइट [स्क्रिप्टबलमेम्बर] विधि में कॉल करता है।

उन सभी विरासत जेएस इंटरफेस को नई सुविधाओं तक पहुंचने के लिए समर्थन के साथ-साथ नए इंटरफ़ेस की आवश्यकता होती है, इसलिए जो कुछ स्वचालित रूप से जेएस इंटरफ़ेस सेट करता है और सही "सिल्वरलाइट विधि" कॉल को "प्रतिनिधि" कॉल करता है, वह बहुत तेज़ी से काम करने में मदद करेगा।

मैं यहां कोड पोस्ट नहीं कर सकता, इसलिए सारांश है।

उत्तर

22

ईमानदार होने के लिए, यदि आप संकलन समय पर प्रकार नहीं जानते हैं, तो Delegate बनाने में बहुत अधिक लाभ नहीं है। आप DynamicInvoke का उपयोग नहीं करना चाहते हैं; यह प्रतिबिंब के रूप में धीमा होगा। इसका मुख्य अपवाद तब होता है जब छाया में एक प्रतिनिधि-प्रकार छिप जाता है, उदाहरण के लिए जब किसी ईवेंट की सदस्यता लेती है - उस स्थिति में EventInfo यह उपलब्ध कराता है।

जानकारी के लिए, Expression पर .NET 3.5 में, वहाँ है:

Expression.GetActionType(params Type[] typeArgs); 
Expression.GetFuncType(params Type[] typeArgs) 

कि एक हद तक मदद कर सकता है:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 
static class Program { 
    static void Main() { 
     DoStuff("Test1"); 
     DoStuff("Test2"); 
    } 
    static void DoStuff(string methodName) { 
     MethodInfo method = typeof(Program).GetMethod(methodName); 
     List<Type> args = new List<Type>(
      method.GetParameters().Select(p => p.ParameterType)); 
     Type delegateType; 
     if (method.ReturnType == typeof(void)) { 
      delegateType = Expression.GetActionType(args.ToArray()); 
     } else { 
      args.Add(method.ReturnType); 
      delegateType = Expression.GetFuncType(args.ToArray()); 
     } 
     Delegate d = Delegate.CreateDelegate(delegateType, null, method); 
     Console.WriteLine(d); 
    } 
    public static void Test1(int i, DateTime when) { } 
    public static float Test2(string x) { return 0; } 
} 
+1

मैं इसे सिल्वरलाइट [स्क्रिप्टबलमेम्बर] और एक अलग जावास्क्रिप्ट इंटरफेस के साथ गोंद बनाने के लिए बना रहा हूं इसलिए मुझे दोनों स्थानों में सिंक में विधि हस्ताक्षर रखने के बारे में चिंता करने की आवश्यकता नहीं है। – chakrit

+0

वाह .... इससे बहुत मदद मिली! तुम लोग कमाल के हो! – chakrit

+0

@ मार्क ग्रेवेल, मैं उपरोक्त कोड जैसे डी() में बनाए गए प्रतिनिधि को आमंत्रित करने में सक्षम नहीं हूं। Googling के बाद मैंने पाया कि गतिशील इन्वोक का उपयोग विधि को आह्वान करने के लिए किया जा सकता है, जो बहुत धीमी है। कृपया मदद करें। मैं प्रतिनिधियों और घटनाओं के लिए नया हूँ। मेरी आवश्यकता है गतिशील रूप से एक विधि का आह्वान करना, संख्या या पैरामीटर के प्रकार रनटाइम पर केवल – Saranya

7

यदि आप पहले से ही संख्या या पैरामीटर को नहीं जानते हैं, तो संभवतः इसका मतलब है कि आप उस प्रतिनिधि प्रकार को नहीं जानते जिसे आप बनाना चाहते हैं?

यदि ऐसा है, तो आप बिल्कुल सामान्य मामले में फंस गए हैं।

हालांकि, ज्यादातर आम मामलों (कोई रेफरी/बाहर पैरामीटर, कुछ पर्याप्त मानकों मौजूदा प्रकार का उपयोग करने के लिए) के लिए आप Func या Action प्रतिनिधियों में से एक के साथ भाग मिल सकता है। (.NET 4.0 में Func/Action प्रकारों की बड़ी संख्या के लिए प्रकार हैं, इसलिए वास्तव में आपको केवल आउट/रेफ पैरामीटर के बारे में चिंता करने की आवश्यकता होगी।) यदि विधि में गैर-शून्य रिटर्न प्रकार Func का उपयोग करता है, अन्यथा Action का उपयोग करें। पैरामीटर की संख्या के आधार पर किस प्रकार का उपयोग करना है, उदाहरण के लिए कार्य करें।

static readonly Type[] FuncTypes = { typeof(Func), 
    typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), /* etc */ }; 

उपयोग Type.MakeGenericType पैरामीटर प्रकार का उपयोग और वापसी सही प्रतिनिधि प्रकार प्राप्त करने के लिए प्रकार, तो Delegate.CreateDelegate काम करना चाहिए।

मेरे पास अभी नमूना तैयार करने का समय नहीं है, लेकिन अगर आप मुझे बाद में चाहते हैं तो मुझे बताएं।

एक प्रश्न: आप इस प्रतिनिधि का उपयोग कैसे करना चाहते हैं? इसे और निष्पादित करने के बारे में जानने के लिए कुछ और करने की ज़रूरत है, निश्चित रूप से ...

+0

एएच-हा ... मेकजेनेरिक टाइप + फनक पर अच्छा ले लो ... यह होगा :-) – chakrit

+4

अपने से बचने के लिए स्थैतिक प्रकार [], अभिव्यक्ति पर विचार करें। गेटएक्शन टाइप/अभिव्यक्ति। गेटफनक टाइप - पोस्ट देखें। मैं ** आशा करता हूं कि ** ये विधियां नए .NET 4.0 प्रकारों को शामिल करने के लिए बढ़ा दी गई हैं। –

+0

मैंने प्रश्न के लिए "क्यों" जोड़ा है – chakrit

6

क्यों है कि जटिल?

public static Delegate CreateDelegate(this MethodInfo method) 
{ 
    return Delegate.CreateDelegate 
    (
     Expression.GetDelegateType 
     (
      method.GetParameters() 
       .Select(p => p.ParameterType) 
       .Concat(new Type[] { method.ReturnType }) 
       .ToArray() 
     ), 
     null, 
     method 
    ); 
} 

[साइड नोट: मैंने इस विधि को "बनाओ ..." उपसर्ग किया है। "टू ..." भ्रमित है क्योंकि यह आपको लगता है कि यह एक रूपांतरण है।]

+0

'Expression.GetDelegateType' विधि वास्तव में .NET 4 और SL 4 विशिष्ट है। मेरा प्रश्न .NET4 और SL4 रिलीज़ से पहले पूछा गया था। वैसे भी उत्तर के लिए धन्यवाद। ध्यान दें कि विधि एक उदाहरण के लिए एक प्रतिनिधि को बाध्य करने की आवश्यकता होगी यदि विधि एक उदाहरण विधि है इसलिए बाध्यकारी भाग अभी भी अनिवार्य है। – chakrit

+0

किसी ऑब्जेक्ट को दूसरे पैरामीटर के रूप में पास करके (जिसे 'फर्स्ट आर्ग्यूमेंट' कहा जाता है - मैं यहां शून्य से गुजर रहा हूं) आप ऑब्जेक्ट निर्दिष्ट कर सकते हैं जिस पर प्रतिनिधि प्रतिनिधि है। या मैं इस बिंदु को याद करता हूँ? – 0xbadf00d

संबंधित मुद्दे