2011-03-22 9 views
8

क्या किसी ऑब्जेक्ट को बाध्यकारी किए बिना किसी प्रतिनिधि को स्टोर करने का कोई तरीका है जैसे आप MethodInfo के साथ कैसे कर सकते हैं? अभी मैं एक MethodInfo संग्रहीत कर रहा हूं, इसलिए मैं इसे विधि को कॉल करने के लिए ऑब्जेक्ट दे सकता हूं। लेकिन मैं इसे एक प्रतिनिधि बनने के बजाय बहुत कुछ है। जैसा कि वहाँ एक विशेषता है जो .NET को बताती है कि पहला पैरामीटर "यह" है?सी # प्रतिनिधि एक उदाहरण के लिए बाध्य नहीं है?

MethodInfo mi; 
Action<string> func; 
mi.Invoke(this,new object[]{str}); 
func(this, str); //Is this possible with a delegate? 
+0

आप थोड़ा और अधिक विवरण के साथ सवाल अलग तरीके से व्यक्त कर सकता है, मुझे लगता है मैं यह आंशिक रूप से लेकिन नहीं मिला सोच सकते हैं ज़रूर। –

+0

मेरा मतलब क्या है इसका एक उदाहरण जोड़ा गया। असल में क्या किसी ऑब्जेक्ट संदर्भ के बिना प्रतिनिधि होना संभव है और इसे कॉल करते समय इसे ऑब्जेक्ट देना संभव है? – Will

+1

मैंने इसे स्पष्ट करने के लिए आपके प्रश्न का शीर्षक बदल दिया। अगर आपको यह पसंद नहीं है तो वापस रोल करने के लिए स्वतंत्र महसूस करें;) –

उत्तर

11

जो आप चाहते हैं उसे open instance delegate कहा जाता है। यह सी # भाषा में सीधे समर्थित नहीं है, लेकिन सीएलआर इसका समर्थन करता है।

असल में, एक खुला उदाहरण प्रतिनिधि सामान्य प्रतिनिधि के समान होता है, लेकिन सामान्य पैरामीटर से पहले this के लिए अतिरिक्त पैरामीटर लेता है, और इसमें एक शून्य लक्ष्य (स्थिर विधि के लिए प्रतिनिधि की तरह) होता है। उदाहरण के लिए, Action<T> के खुले उदाहरण बराबर होगा:

delegate void OpenAction<TThis, T>(TThis @this, T arg); 

यहां एक संपूर्ण उदाहरण है:

void Main() 
{ 
    MethodInfo sayHelloMethod = typeof(Person).GetMethod("SayHello"); 
    OpenAction<Person, string> action = 
     (OpenAction<Person, string>) 
      Delegate.CreateDelegate(
       typeof(OpenAction<Person, string>), 
       null, 
       sayHelloMethod); 

    Person joe = new Person { Name = "Joe" }; 
    action(joe, "Jack"); // Prints "Hello Jack, my name is Joe" 
} 

delegate void OpenAction<TThis, T>(TThis @this, T arg); 

class Person 
{ 
    public string Name { get; set; } 

    public void SayHello(string name) 
    { 
     Console.WriteLine ("Hi {0}, my name is {1}", name, this.Name); 
    } 
} 

अधिक जानकारी के लिए this article पर एक नज़र डालें।

+0

शर्म की बात है कि सी # सीधे इसका समर्थन नहीं करता है। जानकारी के लिए धन्यवाद: डी। – Will

5

आप एक MethodInfo के लिए एक जोरदार टाइप प्रतिनिधि बनाने के लिए Delegate.CreateDelegate विधि का उपयोग कर सकते हैं।

आप संकलन समय पर विधि के हस्ताक्षर नहीं जानते हैं, तो आप एक Func<...> प्रतिबिंब का उपयोग कर बना सकते हैं, या एक लैम्ब्डा अभिव्यक्ति है कि invokes MethodInfo बनाएँ:

MethodInfo methodInfo = ...; 
object thisObj = ...; 
Func<object[]> callMethod = args => methodInfo.Invoke(thisObj, args); 

(यह currying कहा जाता है)

ध्यान दें कि प्रतिनिधिमंडल को हर बार प्रतिबिंबित करने से प्रदर्शन को प्रभावित किया जाएगा, Delegate.CreateDelegate के विपरीत।

+0

इसे अच्छे बनाने के लिए लैम्ब्डा का उपयोग करने के बारे में नहीं सोचा था, धन्यवाद। – Will

0

एक प्रतिनिधि अनिवार्य रूप से केवल MethodInfo (वास्तव में, MethodBase) और एक ऑब्जेक्ट संदर्भ है, प्रदर्शन के लिए कुछ आंतरिक पॉइंटर्स के साथ। तो यदि आपके पास MethodInfo है, तो आपके पास अनिवार्य रूप से एक अनबाउंड प्रतिनिधि होगा। आपका विशिष्ट उपयोग केस क्या है?

+1

कार्यात्मक रूप से, हाँ, यह मोटे तौर पर वही है। लेकिन MethodInfo.Invoke एक प्रतिनिधि को आमंत्रित करने से बहुत धीमी है ... –

+0

@ थॉमस लेवेस्क: अनुमोदित। बार-बार कॉल के लिए, 'प्रतिनिधि को कॉल करके प्रदर्शन में सुधार किया जा सकता है।एक बाध्य प्रतिनिधि बनाने के लिए CreateDelegate() 'बनाएं, लेकिन मुझे लगता है कि एक बाइंड-कॉल-डिस्कार्ड के लिए, बाइंड-कॉल-डिस्कार्ड पैटर्न, यह कोई प्रदर्शन लाभ प्रदान नहीं करेगा। –

0

क्यों नहीं बस

Action<T, string> unbound = (This, str) => This.Method(str); 

ताकि आप

unbound(instanceA, "hello"); 
unbound(instanceB, "world"); 

या यहाँ तक कि

Action<string> bound = str => unbound(instanceC, str); 
संबंधित मुद्दे