ExpandoObject, डायनामोऑब्जेक्ट और डायनेमिक के बीच अंतर


170

और System.Dynamic.ExpandoObject, के बीच अंतर क्या हैं ?System.Dynamic.DynamicObjectdynamic

आप किन स्थितियों में इन प्रकारों का उपयोग करते हैं?

जवाबों:


154

dynamicकीवर्ड चर है कि देर-बाउंड किया जाना चाहिए घोषित करने के लिए प्रयोग किया जाता है।
यदि आप किसी वास्तविक या कल्पना प्रकार के लिए देर से बाध्यकारी का उपयोग करना चाहते हैं, तो आप dynamicकीवर्ड का उपयोग करते हैं और कंपाइलर बाकी काम करता है।

जब आप dynamicकिसी सामान्य उदाहरण के साथ इंटरैक्ट करने के लिए कीवर्ड का उपयोग करते हैं , तो DLR इंस्टेंस के सामान्य तरीकों से लेट-बाउंड कॉल करता है।

IDynamicMetaObjectProviderइंटरफ़ेस एक वर्ग इसके देर से बाध्य व्यवहार का नियंत्रण लेने के लिए अनुमति देता है।
जब आप dynamicकिसी IDynamicMetaObjectProviderकार्यान्वयन के साथ बातचीत करने के लिए कीवर्ड का उपयोग करते हैं , तो DLR IDynamicMetaObjectProviderविधियों को कॉल करता है और ऑब्जेक्ट स्वयं निर्णय लेता है कि क्या करना है।

ExpandoObjectऔर DynamicObjectवर्गों के कार्यान्वयन हैं IDynamicMetaObjectProvider

ExpandoObjectएक साधारण वर्ग है जो आपको सदस्यों को एक उदाहरण में जोड़ने और dynamicसहयोगी का उपयोग करने की अनुमति देता है ।
DynamicObjectएक अधिक उन्नत कार्यान्वयन है जिसे आसानी से अनुकूलित व्यवहार प्रदान करने के लिए विरासत में मिला जा सकता है।


2
इस बारे में अधिक जानने के लिए एक अच्छी जगह क्या होगी? एपीआई नहीं लेकिन एपीआई के पीछे क्यों? उदाहरण के लिए डायनेमिकऑबजेक्ट से डिटेलऑबजेक्ट क्यों नहीं निकलता है, जो रूबी की 'मेथड_मिसिंग' आधारित प्रोग्रामिंग के लिए डिफैक्टो बेस प्रकार दिखता है।
गिषु

4
क्या आप कुछ उपयोग उदाहरण जोड़ सकते हैं? उदाहरण के लिए, मैं डायनेमिक ऑबजेक्ट का उपयोग कैसे करूंगा, और इसके क्या फायदे हैं?
o

10
इस तरह के उदाहरण के बिना महान जवाब शीर्ष पर क्रीम के बिना केक की तरह हैं।
तेमन शिपाही


68

मैं इस प्रश्न का स्पष्ट उत्तर देने का प्रयास करूंगा, ताकि स्पष्ट रूप से समझाया जा सके कि गतिशील ExpandoObjectऔर , के बीच क्या अंतर हैं DynamicObject

बहुत जल्दी, dynamicएक खोजशब्द है। यह एक प्रकार प्रति-से नहीं है। यह एक खोजशब्द है जो संकलक को डिज़ाइन-समय पर स्थैतिक प्रकार की जाँच को अनदेखा करने और इसके बजाय रन-टाइम पर लेट-बाइंडिंग का उपयोग करने के लिए कहता है। तो हम dynamicइस उत्तर के बाकी हिस्सों में ज्यादा समय नहीं बिताएंगे ।

ExpandoObjectऔर DynamicObjectवास्तव में प्रकार हैं। सर्फ़ पर, वे एक-दूसरे के समान दिखते हैं। दोनों वर्ग लागू करते हैं IDynamicMetaObjectProvider। हालांकि, गहरी खुदाई करें और आप पाएंगे कि वे समान नहीं हैं।

डायनामिकऑब्जेक्ट IDynamicMetaObjectProviderविशुद्ध रूप से डेवलपर्स के लिए एक प्रारंभिक कार्यान्वयन है, जो डायनेमिक प्रेषण कार्य करने के लिए कस्टम अंतर्निहित भंडारण और पुनर्प्राप्ति व्यवहार के साथ गतिशील प्रेषण का समर्थन करने वाले अपने स्वयं के कस्टम प्रकारों को लागू करने के लिए एक प्रारंभिक बिंदु है।

  1. डायनामिकऑब्जेक्ट का निर्माण सीधे नहीं किया जा सकता है।
  2. डेवलपर के रूप में आपके पास इसका कोई उपयोग होने के लिए आप डायनामिकऑब्जेक्ट का विस्तार करें।
  3. जब आप डायनामिकऑब्जेक्ट का विस्तार करते हैं, तो आप रन-टाइम में अपने अंतर्निहित डेटा प्रतिनिधित्व में आंतरिक रूप से संग्रहीत डेटा को हल करने के लिए डायनेमिक प्रेषण कैसे चाहते हैं, इसके बारे में अब कस्टम व्यवहार प्रदान करने में सक्षम हैं।
  4. ExpandoObject एक शब्दकोश, आदि में अंतर्निहित डेटा संग्रहीत करता है। यदि आप डायनामिकऑब्जेक्ट को कार्यान्वित करते हैं, तो आप जहाँ चाहें और जहाँ भी चाहें डेटा संग्रहीत कर सकते हैं। (उदाहरण के लिए आप कैसे प्राप्त करते हैं और डेटा को प्रेषण पर सेट करते हैं, पूरी तरह आप पर निर्भर है)।

संक्षेप में, डायनेमिकऑब्जेक्ट का उपयोग तब करें जब आप अपने खुद के प्रकार बनाना चाहते हैं जो डीएलआर के साथ उपयोग किए जा सकते हैं और जो भी कस्टम व्यवहार आप चाहें, उसके साथ काम कर सकते हैं।

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

आप निम्नानुसार एक प्रकार बना सकते हैं: (ध्यान दें, नीचे दिया गया कोड केवल चित्रण के लिए है और नहीं चल सकता है। डायनेमिकऑब्जेक्ट का सही तरीके से उपयोग कैसे करें, इसके बारे में जानने के लिए, कई लेख और ट्यूटोरियल अन्यत्र हैं।)

public class MyNoCookiesInTheJarDynamicObject : DynamicObject
{
    Dictionary<string, object> properties = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (properties.ContainsKey(binder.Name))
        {
            result = properties[binder.Name];
            return true;
        }
        else
        {
            result = "I'm sorry, there are no cookies in this jar!"; //<-- THIS IS OUR 
            CUSTOM "NO COOKIES IN THE JAR" RESPONSE FROM OUR DYNAMIC TYPE WHEN AN UNKNOWN FIELD IS ACCESSED
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        properties[binder.Name] = value;
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        dynamic method = properties[binder.Name];
        result = method(args[0].ToString(), args[1].ToString());
        return true;
    }
}

अब, हम इस काल्पनिक वर्ग का उपयोग कर सकते हैं जिसे हमने केवल एक गतिशील प्रकार के रूप में बनाया है, जिसमें यदि फ़ील्ड मौजूद नहीं है तो एक बहुत ही कस्टम व्यवहार है।

dynamic d = new MyNoCookiesInTheJarDynamicObject();
var s = d.FieldThatDoesntExist;

//in our contrived example, the below should evaluate to true
Assert.IsTrue(s == "I'm sorry, there are no cookies in this jar!")

ExpandoObjectका एक पूर्ण कार्यान्वयन है IDynamicMetaObjectProvider, जहां .NET फ्रेमवर्क टीम ने आपके लिए इन सभी निर्णयों को बनाया है। यह उपयोगी है अगर आपको किसी भी कस्टम व्यवहार की आवश्यकता नहीं है, और आपको लगता है कि एक्सपेंडीओबजेक्ट आपके लिए पर्याप्त काम करता है (90% समय, ExpandoObjectकाफी अच्छा है)। इसलिए, उदाहरण के लिए, निम्नलिखित देखें, और वह यह कि ExpandoObject के लिए, डिजाइनरों ने एक अपवाद फेंकना चुना अगर गतिशील सदस्य मौजूद नहीं है।

dynamic d = new ExpandoObject();

/*
The ExpandoObject designers chose that this operation should result in an 
Exception. They did not have to make that choice, null could 
have been returned, for example; or the designers could've returned a "sorry no cookies in the jar" response like in our custom class. However, if you choose to use 
ExpandoObject, you have chosen to go with their particular implementation 
of DynamicObject behavior.
*/

try {
var s = d.FieldThatDoesntExist;
}
catch(RuntimeBinderException) { ... }

इसलिए सारांशित करने के लिए, ExpandoObjectडायनेमिकऑब्जेक्ट को विस्तारित करने के लिए बस एक पूर्व-चुना हुआ तरीका है जो कुछ गतिशील प्रेषण व्यवहारों के साथ है जो संभवतः आपके लिए काम करेंगे , लेकिन आपकी विशेष आवश्यकताओं के आधार पर नहीं हो सकते।

जबकि, DyanmicObjectएक सहायक आधार है जो अद्वितीय गतिशील व्यवहार के साथ अपने स्वयं के प्रकारों को सरल और आसान लागू करता है।

एक उपयोगी ट्यूटोरियल जिस पर ऊपर दिए गए उदाहरण स्रोत का बहुत कुछ आधारित है।


बहुत अच्छी व्याख्या। केवल एक तकनीकी सुधार: ExpandoObject डायनामिकऑब्जेक्ट से वारिस नहीं होता है।
माइक रोज़ॉफ्ट

उदाहरण के लिए एक छोटा सुधार DynamicObject: जब ओवरराइडिंग TryGetMember, यदि आप झूठे वापस करते हैं तो RuntimeBinderExceptionगैर-मौजूदा संपत्ति तक पहुंचने की कोशिश करते समय फेंक दिया जाएगा। स्निपेट के लिए वास्तव में काम करने के लिए आपको वापस लौटना चाहिए true
lluchmk

36

C के अनुसार # भाषा विनिर्देश dynamicएक प्रकार की घोषणा है। Ie का dynamic xअर्थ है कि चर xका प्रकार है dynamic

DynamicObjectएक प्रकार है जो इसे लागू करना आसान बनाता है IDynamicMetaObjectProviderऔर इस प्रकार प्रकार के लिए विशिष्ट बाध्यकारी व्यवहार को ओवरराइड करता है।

ExpandoObjectएक प्रकार है जो प्रॉपर्टी बैग की तरह काम करता है। यानी आप रनटाइम के दौरान इस प्रकार के डायनेमिक इंस्टेंस के गुण, तरीके और इसके आगे जोड़ सकते हैं।


25
dynamicएक वास्तविक प्रकार नहीं है ... यह संकलक को इस चर के लिए देर से बाध्यकारी का उपयोग करने के लिए बताने के लिए सिर्फ एक संकेत है। dynamicचर वास्तव objectमें MSIL के रूप में घोषित किए जाते हैं
थॉमस लेवेस्क

1
@ थोमस: संकलक के दृष्टिकोण से यह एक प्रकार है, लेकिन आप सही हैं कि रनटाइम प्रतिनिधित्व ऑब्जेक्ट का है। आपको कई एमएस प्रस्तुतियों में "स्टेटिकली टाइप्ड टू डायनामिक" स्टेटमेंट मिलेगा।
ब्रायन रासमुसेन

3
@ थोमस: और भाषा की युक्ति कहती है "C # 4.0 एक नया स्थिर प्रकार पेश करता है जिसे डायनामिक कहा जाता है"।
ब्रायन रासमुसेन

वास्तव में ... लेकिन मुझे लगता है कि यह एक प्रकार के रूप में विचार करने के लिए भ्रमित करने वाला है, क्योंकि डायनेमिकऑब्जेक्ट या एक्सपेंडेओओबजेक्ट जैसे प्रकारों के साथ विरासत का कोई संबंध नहीं है
थॉमस लेवेस्क

3
@ नताना मैं तुम्हारे साथ यहाँ हूँ। हालाँकि, भाषा विनिर्देश इसे एक प्रकार कहता है, इसलिए मैं इसके साथ जा रहा हूं।
ब्रायन रासमुसेन

0

उपरोक्त उदाहरण DynamicObjectस्पष्ट रूप से अंतर नहीं बताता है, क्योंकि यह मूल रूप से कार्यक्षमता को लागू कर रहा है जो पहले से ही प्रदान किया गया है ExpandoObject

नीचे दिए गए दो लिंक में, यह बहुत स्पष्ट है कि इसकी मदद से DynamicObjectवास्तविक प्रकार ( XElementनीचे दिए गए लिंक में उपयोग किए गए उदाहरण में) को संरक्षित / परिवर्तित करना और गुणों और विधियों पर बेहतर नियंत्रण करना संभव है।

https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-introducing-the-expandoobject/

https://blogs.msdn.microsoft.com/csharpfaq/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject/

public class DynamicXMLNode : DynamicObject    
{    
    XElement node;

    public DynamicXMLNode(XElement node)    
    {    
        this.node = node;    
    }

    public DynamicXMLNode()    
    {    
    }

    public DynamicXMLNode(String name)    
    {    
        node = new XElement(name);    
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)    
    {    
        XElement setNode = node.Element(binder.Name);

        if (setNode != null)    
            setNode.SetValue(value);    
        else    
        {    
            if (value.GetType() == typeof(DynamicXMLNode))    
                node.Add(new XElement(binder.Name));    
            else    
                node.Add(new XElement(binder.Name, value));    
        }

        return true;    
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)    
    {    
        XElement getNode = node.Element(binder.Name);

        if (getNode != null)    
        {    
            result = new DynamicXMLNode(getNode);    
            return true;    
        }    
        else    
        {    
            result = null;    
            return false;    
        }    
    }    
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.