2009-06-07 13 views
6

क्या dynamic विधि कॉल (विशेष रूप से वे RuntimeBinderException एस बढ़ाने के लिए जा रहे हैं) RealProxy के साथ किसी को भी अवरुद्ध करने के तरीके से जानते हैं? मैं अपवाद को पकड़ने और उसके ऊपर 'विधि अनुपलब्ध' को लागू करने की उम्मीद कर रहा था, लेकिन ऐसा लगता है कि इंटरसेप्टर को देखने में सक्षम होने से पहले इसे फेंक दिया जाता है।सी # 4.0 में विधि-गायब कठिनाइयों: गतिशील बनाम रियलप्रोक्सी

मेरा परीक्षण बस लगता है कि:

dynamic hello = MethodMissingInterceptor<DynamicObject>.Create(); 
Assert.AreEqual("World", hello.World()); 

कहाँ World वास्तव में DynamicObject पर लागू नहीं है। इंटरसेप्टर बिल्कुल स्पष्ट है - मैं RuntimeBinderException के लिए IMethodReturnMessage.Exception की जाँच करें और की तरह कुछ करने के लिए पर अग्रेषित करने के लिए उम्मीद कर रहा था:

public IMessage MethodMissing(IMethodCallMessage call) 
{ 
    return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call); 
} 

दुर्भाग्य से, सब मैं अपने इंटरसेप्टर में देखते हैं GetType करने के लिए कुछ कॉल, और नहीं गैर existant World तरीका है ।

विफल होने पर - क्या किसी को पता है कि DynamicProxy संस्करण .NET 4.0 पर खुशी से चल रहा है, फिर भी समस्या का सामना करना पड़ सकता है?

उत्तर

17

मैं लंबे उत्तर से शुरू करूंगा। सी # में एक गतिशील आपरेशन के हर बाँध इस क्रम में लगभग इन तीन चीजों करता है:

  1. वस्तु पूछो ही बाध्य करने के लिए अगर यह IDynamicMetaObjectProvider लागू करता है या एक COM वस्तु है, और है कि अगर विफल रहता है, तो ...
  2. प्रतिबिंब का उपयोग करके एक सादे-पुराने-clr-object पर ऑपरेशन को बाध्य करें, और यदि यह विफल हो जाता है, तो ...
  3. एक डायनामिक मेटाऑब्जेक्ट लौटाएं जो बांधने की कुल विफलता का प्रतिनिधित्व करता है।

आप GetType देख रहे हैं कॉल क्योंकि चरण 2 में, सी # क्रम बांधने की मशीन तुम पर दर्शाती है यदि आप एक "दुनिया" विधि है कि कॉल करने के लिए उचित है यह पता लगाने की कोशिश करने के लिए, और इस वजह से हो रहा है हैलो के IDynamicMetaObjectProvider कार्यान्वयन, यदि कोई है, तो कुछ भी करने के लिए विशेष नहीं हो सकता है।

दुर्भाग्य से आपके लिए, जब तक RuntimeBinderException फेंक दिया गया है, हम अब बाध्यकारी नहीं हैं। चरण 3 के कारण लौटा मेटा ऑब्जेक्ट के जवाब में गतिशील संचालन के निष्पादन चरण से अपवाद आता है। इसे पकड़ने का एकमात्र अवसर वास्तविक कॉल साइट पर है।

तो यदि आप सी # में method_missing को कार्यान्वित करना चाहते हैं तो रणनीति आपके लिए काम नहीं कर रही है। हालांकि आपके पास कुछ विकल्प हैं।

एक आसान विकल्प ID MethodMetaObjectProvider को आपके MethodMissingInterceptor में कार्यान्वित करना है, और लपेटा हुआ ऑब्जेक्ट के IDMOP कार्यान्वयन को रोकना है। आंतरिक IDMOP के हिस्से में विफलता के मामले में, आप जो कुछ भी चाहते हैं उसे बाध्य कर सकते हैं (शायद इंटरसेप्टर में संग्रहीत विधि_missing प्रतिनिधि को कॉल करें)। यहां नकारात्मकता यह है कि यह केवल उन वस्तुओं के लिए काम करता है जो गतिशील वस्तुओं के लिए जाने जाते हैं, उदा। जो IDMOP को लागू करने के लिए लागू करते हैं। इसका कारण यह है कि आप मूल रूप से चरण 1 और 2.

एक अन्य विकल्प मैं IDynamicMetaObjectProvider लागू करने के लिए है के बारे में सोच सकते हैं के बीच अपने आप को डालने जाता है, और उस में, हर बाँध को सकारात्मक जवाब, एक विधि है कि (क) का उत्पादन करने के लिए एक कॉल लौटने वही कोड सी # कंपाइलर पहले स्थान पर बांधने के लिए उत्पादित होता, और (बी) एक विधि_मापिंग विधि को कॉल करने के लिए RuntimeBinderException को पकड़ता है।यहां नकारात्मक बात यह है कि यह काफी जटिल होगा - आपको मनमाने ढंग से प्रतिनिधि प्रकार और आईएल जो उन्हें उपयोग करता है, सी # रनटाइम बाइंडर असेंबली में सार्वजनिक प्रकारों के खिलाफ उत्पन्न करने की आवश्यकता होगी, जो स्पष्ट रूप से सार्वजनिक उपभोग के लिए नहीं हैं। लेकिन कम से कम आप सभी परिचालनों के खिलाफ विधि गायब हो जाएगा।

मुझे यकीन है कि ऐसी अन्य रणनीतियां हैं जिनके बारे में मैंने नहीं सोचा है, जैसे कि आप रिमोटिंग प्रॉक्सी का उपयोग करने के बारे में सोच रहे हैं। मैं कल्पना नहीं कर सकता कि वे क्या दिखते हैं और मैं यह नहीं कह सकता कि वे सफल होंगे या नहीं।

यहां समस्या का क्रूक्स यह है कि सी # 4.0 में ऐसा डिज़ाइन नहीं है जो ऐसा करने की आपकी इच्छा का अनुमान लगाए। विशेष रूप से, आप चरण 2 और 3 के बीच आसानी से खुद को सम्मिलित नहीं कर सकते हैं। यह मुझे संक्षिप्त उत्तर में लाता है, जो खेद है, सी # 4.0 में method_missing नहीं है।

+0

उत्कृष्ट स्पष्टीकरण के लिए धन्यवाद, क्रिस - मैंने अभी आपके ब्लॉग पर सी # गतिशील 'पोस्ट की श्रृंखला शुरू कर दी है। :) मेरे उद्देश्यों के लिए, आपका पहला समाधान ऐसा लगता है जैसे इसे काम करना चाहिए। मैं केवल इन कॉलरों को बिल्डर-स्टाइल ऑब्जेक्ट्स के लिए बनाना चाहता हूं और परीक्षण एपीआई में कुछ अतिरिक्त प्रवाह के लिए, मुझे उन्हें मनमानी वस्तुओं पर पकड़ने की आवश्यकता नहीं है। – Thom

+0

@ क्रिस - नोट भी "बस मामले में" ऊपर सवाल है; असल में, मुझे यह जानना अच्छा लगेगा ;-p –

+0

क्या वास्तव में इसे कॉल किए बिना किसी सदस्य की उपस्थिति के लिए डायनामिक ऑब्जेक्ट से पूछने का कोई तरीका है? –

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