2009-06-04 2 views
7

मैंने देखा है कि प्रतिनिधि वर्ग एक लक्ष्य संपत्ति है, कि (शायद) उदाहरण प्रतिनिधि पद्धति पर निष्पादित करेंगे देता है।एक शून्य लक्ष्य के साथ एक उदाहरण विधि में एक प्रतिनिधि कैसे बनाएँ?

void PossiblyExecuteDelegate(Action<int> method) 
{ 
    if (method.Target == null) 
    { 
     // delegate instance target is null 
     // do something 
    } 
    else 
    { 
     method(10); 
     // do something else 
    } 
} 

जब यह बुला, मैं की तरह कुछ करना चाहता हूँ: मैं इस तरह कुछ करना चाहता हूँ

class A 
{ 
    void Method(int a) {} 

    static void Main(string[] args) 
    { 
     A a = null; 
     Action<int> action = a.Method; 
     PossiblyExecuteDelegate(action); 
    } 
} 

लेकिन मैं एक ArgumentException (प्रतिनिधि एक उदाहरण विधि करने के लिए मिल एक अशक्त 'इस नहीं हो सकता ') जब मैं प्रतिनिधि बनाने की कोशिश करता हूं। क्या मैं संभव करना चाहता हूं, और मैं इसे कैसे कर सकता हूं?

+0

क्यों आप ऐसा करना चाहते हैं? आपके पास ऐसे उदाहरण हैं जो शून्य हैं? –

उत्तर

15

AHAH! found it!

आप अंतर्निहित 'इस' पहला तर्क स्पष्ट रूप से निर्दिष्ट के साथ एक प्रतिनिधि का उपयोग कर एक CreateDelegate अधिभार का उपयोग कर एक खुला उदाहरण प्रतिनिधि बना सकते हैं:

delegate void OpenInstanceDelegate(A instance, int a); 

class A 
{ 
    public void Method(int a) {} 

    static void Main(string[] args) 
    { 
     A a = null; 
     MethodInfo method = typeof(A).GetMethod("Method"); 
     OpenInstanceDelegate action = (OpenInstanceDelegate)Delegate.CreateDelegate(typeof(OpenInstanceDelegate), a, method); 

     PossiblyExecuteDelegate(action); 
    } 
} 
+0

हां, जैसा कि मैंने अपनी प्रतिक्रिया संपादित की है, यह प्रतिबिंब के साथ संभव है, लेकिन मानक संकलित .NET कोड के साथ नहीं। क्या आपकी चिंता है कि लोग आपको प्रतिबिंबित प्रतिनिधि घोषित कर देंगे? –

1

ऐसा करने में आप PossiblyExecuteDelegate() करने के लिए एक static विधि से पारित करना होगा। यह आपको nullTarget देगा।

class A 
{ 
    void Method(int a) {} 
    static void Method2(int a) {} 

    static void Main(string[] args) 
    { 
     PossiblyExecuteDelegate(A.Method2); 

     A a = new A(); 

     PossiblyExecuteDelegate(a.Method); 
    } 
} 

संपादित करें: यह प्रतिबिंब के माध्यम से कोई लक्ष्य के साथ एक उदाहरण विधि के लिए एक प्रतिनिधि पारित करने के लिए है संभव है, लेकिन का उपयोग नहीं कर मानक संकलित कोड।

+0

मेरा मतलब है कि परीक्षण विधि को शून्य उदाहरण पर बुलाया जाएगा, अगर इसे कहा जाता है। समस्या पहली जगह में हो रही है। मैं खुले प्रतिनिधियों के बारे में कुछ पढ़ने याद है, लेकिन मैं छिपाना है और न ही अब इसके बारे में बाल नहीं मिल सकता है ... – thecoop

+0

बस डॉक्स फिर से पाया - आप एक Delegate.CreateDelegate अधिभार का उपयोग कर एक खुला उदाहरण प्रतिनिधि बना सकते हैं (विवरण के साथ एक उत्तर पोस्ट किया) – thecoop

+0

@thecoop: हाँ, मुझे ध्यान दिया जाना चाहिए कि यह प्रतिबिंब के साथ संभव होगा, लेकिन किसी भी संकलन-समय-सुरक्षित कोड के साथ नहीं। उत्तर संपादित किया गया। –

0

यह Delegate.CreateDelegate के साथ संभव है, वास्तव में अधिभार के साथ हस्ताक्षर के साथ: CreateDelegate (Type, object, MethodInfo)

आप दूसरा पैरामीटर (लक्ष्य) तो आप प्रतिनिधि प्रकार में एक अतिरिक्त पैरामीटर डालने का है, कि उदाहरण के प्रकार को निर्दिष्ट, और क के लिए "अशक्त" निर्दिष्ट करते हैं यदि आप प्रतिनिधि को आमंत्रित करते हैं, तो उदाहरण को विधि के "वास्तविक" पैरामीटर के बाद, पहले तर्क के रूप में पारित किया जाना चाहिए।

class Test 
{ 
    public int AddStrings(string a, string b) 
    { 
     return int.Parse(a) + int.Parse(b); 
    } 

    static void Main() 
    { 
     var test = new Test(); 
     var methodInfo = test.GetType().GetMethod("AddStrings"); 
     // note the first extra parameter of the Func, is the owner type 
     var delegateType = typeof(Func<Test, string, string, int>); 
     var del = Delegate.CreateDelegate(delegateType, null, methodInfo); 

     var result = (int)del.DynamicInvoke(test, "39", "3"); 
    } 
} 
संबंधित मुद्दे