8

में सदस्यों को जोड़ना मैं सदस्यों को गतिशील रूप से गतिशील वस्तु में जोड़ने का एक तरीका ढूंढ रहा हूं। ठीक है, मुझे लगता है कि एक छोटे से स्पष्टीकरण की जरूरत है ...गतिशील रूप से गतिशील वस्तु

आपको लगता है कि जब कार्य करें:

dynamic foo = new ExpandoObject(); 
foo.Bar = 42; 

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

मैं कैसे एक कस्टम गतिशील वस्तु (मैं वास्तव में blogged about it कुछ महीने पहले) के साथ ऐसा करना, DynamicObject वर्ग के तरीकों का उपयोग कर पता है, लेकिन मैं इसे कैसे किसी भी गतिशील वस्तु के साथ कर सकते हैं?

मैं शायद IDynamicMetaObjectProvider इंटरफ़ेस का उपयोग कर सकता हूं, लेकिन मुझे समझ में नहीं आता कि इसका उपयोग कैसे किया जाए। उदाहरण के लिए, मुझे GetMetaObject विधि में किस तर्क को पास करना चाहिए? (यह Expression की अपेक्षा करता है)

और वैसे, आप गतिशील वस्तुओं पर प्रतिबिंब कैसे करते हैं? "नियमित" प्रतिबिंब और TypeDescriptor गतिशील सदस्यों को नहीं दिखाते हैं ...

किसी भी अंतर्दृष्टि की सराहना की जाएगी!

+0

सी # 6.0 में, * हो सकता है * आप इसे 'foo। $ Bar = 42;' जैसे लिख सकते हैं। :) सुनिश्चित नहीं है कि यह गतिशील के लिए अनुमति है ... – nawfal

+0

@nawfal, वास्तव में, यह सुविधा गिरा दी गई है .. लेकिन वैसे भी, 'foo। $ bar'' foo ["bar"] ' –

+0

थॉमस के लिए सिर्फ लघुरूप है, इसे छोड़ने की सुविधा के बारे में नहीं पता था (मुझे इसके बारे में खुशी है), लेकिन ओह हाँ, एक पल के लिए मैंने आपके क्यू की वास्तविक आवश्यकता को नजरअंदाज कर दिया। – nawfal

उत्तर

9

जो आप चाहते हैं वह पाइथन के गेटैटर/सेटैटर कार्यों के समान है। सी # या वीबी.नेट में ऐसा करने के बराबर तरीके से कोई निर्मित नहीं है। डीएलआर की बाहरी परत (जो माइक्रोसॉफ्ट .Scripting.dll में जहाजों w/IronPython और IronRuby) में होस्टिंग एपीआई का एक सेट शामिल है जिसमें ऑब्जेक्टऑपरेशंस एपीआई शामिल है जिसमें GetMember/SetMember विधियां हैं। आप उन लोगों का उपयोग कर सकते हैं लेकिन आपको डीएलआर और डीएलआर आधारित भाषा की अतिरिक्त निर्भरता की आवश्यकता होगी।

शायद सबसे आसान तरीका कॉलसाइट W/मौजूदा सी # बाइंडरों में से एक बनाना होगा। आप ildasm या परावर्तक में "foo.Bar = 42" के परिणाम देखकर इसके लिए कोड प्राप्त कर सकते हैं। लेकिन इस का एक सरल उदाहरण होगा:

object x = new ExpandoObject(); 
CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
      Binder.SetMember(
       Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None, 
       "Foo", 
       null, 
       new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) } 
      ) 
     ); 
site.Target(site, x, 42); 
Console.WriteLine(((dynamic)x).Foo); 
+0

मुझे यह सुनिश्चित करने के लिए कुछ समय लेना होगा कि मैं वास्तव में समझता हूं कि यह कोड क्या कर रहा है, लेकिन फिर भी यह ठीक काम कर रहा है ... धन्यवाद! –

+0

क्या यह संभव है <.NET 4.0 डीएलआर का उपयोग करना संभव है? ऐसा लगता है कि गतिशीलता का उपयोग इसे रोक देगा। – Firestrand

+0

उपरोक्त विधि ठीक से काम नहीं करना चाहिए। सेटर कॉल साइट 2 तर्क infos हो जाएगा 1. के बजाय सही परिभाषा प्रदान करने की आवश्यकता है: नई [] { CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, नल), CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, नल) } –

5

ओपनसोर्स ढांचे Dynamitey (nuget के माध्यम से उपलब्ध है) यह कर देगा। यह अभी भी कॉल साइट और बाइंडर कोड को कैशिंग करते समय encapsulates है कि @ Dino-Viehland का उपयोग किया जाता है।

Dynamic.InvokeSet(foo,"Bar",42); 

यह कई other kinds of c# binder too भी कॉल कर सकता है।

5

ExpandoObject उपकरण IDictionary < स्ट्रिंग, ऑब्जेक्ट > स्पष्ट रूप से यद्यपि। इसका अर्थ यह है कि आप आसानी से ExpictionaryObject को IDictionary < स्ट्रिंग, ऑब्जेक्ट > पर डालें और शब्दकोश में हेरफेर कर सकते हैं।

dynamic foo = new ExpandoObject(); 
foo.Bar = 42; 
food = (IDictionary<string,object>)foo; 
food["Baz"] = 54 
+0

धन्यवाद! वास्तव में ExpandoObject IDictionary लागू करता है, जैसा कि मैंने बाद में महसूस किया, इसलिए यह उस मामले में स्पष्ट रूप से सबसे सरल समाधान है। हालांकि मेरे प्रश्न का दायरा व्यापक था: मैं ऐसे समाधान की तलाश में था जो किसी गतिशील वस्तु के साथ काम करेगा, न केवल ExpandoObject –

1

मैं जानता हूँ कि यह काफी एक पुराने पोस्ट है, लेकिन मैंने सोचा कि मैं Miron Abramson solution साथ कैसे आप अपने खुद के प्रकार बना सकते हैं पर गुजरती हैं और रनटाइम पर गुण जोड़ना होगा - और मामले किसी में कुछ की तलाश में है बाहर समान।

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