2010-03-19 16 views
11

मैं DynamicObject के साथ प्रयोग कर रहा हूं। मैं जो चीजों को करने का प्रयास करता हूं उनमें से एक है नीचे दिए गए कोड में दिखाए गए अनुसार ref/out तर्कों के मान सेट करना। हालांकि, Main() में i और j के मानों को ठीक से सेट करने में सक्षम नहीं है (भले ही वे TryInvokeMember() में सही ढंग से सेट हों)। क्या किसी को पता है कि DynamicObject ऑब्जेक्ट को ref/out तर्कों के साथ कैसे कॉल करें और विधि के अंदर सेट मानों को पुनर्प्राप्त करने में सक्षम हो?सी # 4.0 'गतिशील' रेफ/आउट तर्क सेट नहीं करता

class Program 
{ 
    static void Main(string[] args) 
    { 
     dynamic proxy = new Proxy(new Target()); 
     int i = 10; 
     int j = 20; 
     proxy.Wrap(ref i, ref j); 
     Console.WriteLine(i + ":" + j); // Print "10:20" while expect "20:10" 
    } 
} 

class Proxy : DynamicObject 
{ 
    private readonly Target target; 

    public Proxy(Target target) 
    { 
     this.target = target; 
    } 

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 
    { 
     int i = (int) args[0]; 
     int j = (int) args[1]; 
     target.Swap(ref i, ref j); 
     args[0] = i; 
     args[1] = j; 
     result = null; 
     return true; 
    } 
} 

class Target 
{ 
    public void Swap(ref int i, ref int j) 
    { 
     int tmp = i; 
     i = j; 
     j = tmp; 
    } 
} 

अद्यतन 7/15: माइक्रोसॉफ्ट की अगली फिल्म के लिए समस्या का समाधान हो करने का दावा नेट http://connect.microsoft.com/VisualStudio/feedback/details/543101/net-4-0s-dynamicobject-doesn-t-set-ref-out-arguments

अद्यतन 2012/09/08: VS.NET 2012 का उपयोग कर परीक्षण किया गया .NET 4.0 और 4.5 दोनों के साथ, पुष्टि करें: यह पहले ही तय हो चुका है।

+0

सटीक डुप्लिकेट: http: // stackoverflow।कॉम/प्रश्न/2268857/सी -4-निर्धारण-पैरामीटर-पास-सेमेंटिक्स-इन-डायनामिक-कॉल – Gabe

+0

@gabe: वास्तव में मैंने यह प्रश्न देखा, लेकिन यह सवाल इस बारे में था कि क्या कोई यह पता लगा सकता है कि कोई पैरामीटर ज्ञात हो सकता है या नहीं रेफ/आउट या नहीं, जो कि मैं यहां पूछ रहा हूं उससे बिल्कुल अलग है। मुझे उस मामले में दिलचस्पी नहीं है क्योंकि मैं 'लक्ष्य' वर्ग में थोड़ा प्रतिबिंब के साथ आ सकता हूं। –

+0

भले ही आपका प्रश्न अलग है, उसके जवाब में आपके प्रश्न का उत्तर शामिल है: * डायनामिक ऑब्जेक्ट "कॉल-बाय-वैल्यू" * – Gabe

उत्तर

5

ऐसा लगता है कि यह एक बग हो सकता है - शायद DynamicObject में। आप इस तरह Proxy करने के लिए एक Wrap विधि जोड़ते हैं: तो फिर

public void Wrap(ref int x, ref int y) 
{ 
    target.Swap(ref x, ref y); 
} 

भले ही यह अभी भी गतिशील रूप से कहा जाता है (यानी Main में कोड ही रहता है) कोड काम करता है ... इसलिए कम से कम सामान्य "कैसे करता है एक गतिशील वस्तु कार्य "परत पास-दर-संदर्भ का समर्थन करता है।

मुझे लगता है कि अगर यह वास्तव में डीएलआर में एक बग है, यह .NET 4 के लिए तय करने के लिए बहुत देर हो चुकी हो सकता है - लेकिन यह वैसे भी, तो यह एक सर्विस पैक में ठीक किया जा सकता है Connect पर रिपोर्टिंग के लायक है। वैकल्पिक रूप से, यदि यह एक जानबूझकर प्रतिबंध/सीमा है, तो इसे एमएसडीएन में स्पष्ट रूप से दस्तावेज किया जाना चाहिए (जो फिलहाल नहीं है, जहां तक ​​मैं देख सकता हूं)।

+0

दिलचस्प कामकाज, धन्यवाद। यह जानना अच्छा है लेकिन स्पष्ट रूप से मैं डायनामिक ऑब्जेक्ट का सहारा नहीं लेगा अगर मुझे प्रत्येक अग्रेषण विधि को कार्यान्वित करना है :)। मैंने आपके सुझाव के अनुसार कनेक्ट करने के लिए एक बग रिपोर्ट सबमिट की है। –

+0

मुझे नहीं लगता कि यह कैसे एक बग हो सकता है क्योंकि यह काम करने का कोई तरीका नहीं है। 'TryInvokeMember' तर्कों के लिए ऑब्जेक्ट्स की एक सरणी लेता है। इनट्स को सरणी में डालने के लिए उन्हें बॉक्स किया जाना चाहिए, जो उन्हें कॉपी करता है। एकमात्र तरीका यह भी आधा काम हो सकता है कि जब गतिशील बाइंडर प्रतिलिपि बना देता है तो कॉल पूर्ण होने के बाद मूल तर्क सरणी से वापस तर्क देता है, लेकिन यह केवल रेफ तर्कों का अनुकरण कर रहा है। – Gabe

+1

@gabe: इस तरह यह काम करता है जब आप प्रतिबिंब का उपयोग करके रेफ पैरामीटर के साथ एक विधि को कॉल करते हैं - और जैसा कि मैंने कहा है, यह तब काम करता है जब विधि स्थिर रूप से प्रदान की जाती है, भले ही इसे * गतिशील रूप से * कहा जा रहा हो। दूसरे शब्दों में, यह डायनामिक मेटाऑब्जेक्ट स्तर पर काम करता है। निश्चित रूप से, इसके संदर्भ में "सत्य" पास की तुलना में कुछ कंक होंगे (उदाहरण के लिए वेरिएबल को विधि कॉल के दौरान अलग किया जाएगा) लेकिन 99% मामलों के लिए मुझे यकीन है कि इससे कोई फर्क नहीं पड़ता। ऐसा लगता है कि इस तथ्य को अनदेखा करना बेहतर होगा कि वे रेफ पैरामीटर पूरी तरह से हैं, जैसा कि अब है। –

2

एक लंबी कहानी कम करने के लिए, डायनामिक ऑब्जेक्ट पास-बाय-रेफरेंस का समर्थन नहीं करता है, तो आप जो करना चाहते हैं वह सीधे संभव नहीं है।

5

यह एक बग नहीं है। जैसा कि पहले से ही कहा गया था, डायनामिक ऑब्जेक्ट TryInvokeMember में रेफरी और आउट पैरामीटर का समर्थन नहीं करता है। इस विधि को पारित सब कुछ "मूल्य से" माना जाता है। जल्द ही, TryInvokeMember विधि इन खोजशब्दों को आसानी से अनदेखा करता है, और यही कारण है कि आपकी विधि काम नहीं करती है।

यदि आप जॉन स्कीट सुझाव का पालन करते हैं और डायनामिक ऑब्जेक्ट से विरासत में प्राप्त कक्षा के भीतर अपनी स्वयं की लपेट विधि बनाते हैं, तो यह थोड़ा अलग परिदृश्य होगा। वर्कफ़्लो इस तरह दिखता है: जब डायनामिक ऑब्जेक्ट के लिए कोई विधि कॉल होता है, तो सी # रनटाइम बाइंडर पहले क्लास में विधि की तलाश करता है। यदि यह एक पा सकता है, तो यह इस विधि को कॉल करता है। इस बिंदु पर, "रेफरी" और "आउट" पैरामीटर के बारे में जानकारी अभी भी संरक्षित है। अगर ऐसा कोई तरीका नहीं मिल रहा है, तो यह TryInvokeMember विधि को कॉल करता है और बस "रेफरी" और "आउट" कीवर्ड के बारे में जानकारी निकालता है और हर चीज़ को "मूल्य के अनुसार" शुरू करता है। याद रखें कि डायनामिक ऑब्जेक्ट को अन्य भाषा के साथ अंतःक्रियाशीलता को समर्थन देना है, जिसमें सभी सी # विशेषताएं नहीं हो सकती हैं।

सच है, "रेफरी" और "आउट" के बारे में जानकारी अब दस्तावेज़ से गायब है। मैं इसे अगले दस्तावेज अद्यतन में जोड़ दूंगा।

+0

अच्छी जानकारी, धन्यवाद! हालांकि, डायनामिक ऑब्जेक्ट को इंटरऑपरेबिलिटी के लिए रेफ/आउट के बारे में परेशान नहीं होना चाहिए, जबकि TryInvokeMember (जो सी # बाइंडर है, जैसा कि मैं आपकी स्पष्टीकरण से समझता हूं) का कॉलर परेशान होना चाहिए और अंदर सेट किए गए तर्क सरणी के आधार पर आउट/रेफ सेट करने का प्रयास करना चाहिए TryInvokeMember। क्या यह नहीं हो सका? क्या यह नहीं होना चाहिए? –

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