जवाबों:
dynamic
कीवर्ड चर है कि देर-बाउंड किया जाना चाहिए घोषित करने के लिए प्रयोग किया जाता है।
यदि आप किसी वास्तविक या कल्पना प्रकार के लिए देर से बाध्यकारी का उपयोग करना चाहते हैं, तो आप dynamic
कीवर्ड का उपयोग करते हैं और कंपाइलर बाकी काम करता है।
जब आप dynamic
किसी सामान्य उदाहरण के साथ इंटरैक्ट करने के लिए कीवर्ड का उपयोग करते हैं , तो DLR इंस्टेंस के सामान्य तरीकों से लेट-बाउंड कॉल करता है।
IDynamicMetaObjectProvider
इंटरफ़ेस एक वर्ग इसके देर से बाध्य व्यवहार का नियंत्रण लेने के लिए अनुमति देता है।
जब आप dynamic
किसी IDynamicMetaObjectProvider
कार्यान्वयन के साथ बातचीत करने के लिए कीवर्ड का उपयोग करते हैं , तो DLR IDynamicMetaObjectProvider
विधियों को कॉल करता है और ऑब्जेक्ट स्वयं निर्णय लेता है कि क्या करना है।
ExpandoObject
और DynamicObject
वर्गों के कार्यान्वयन हैं IDynamicMetaObjectProvider
।
ExpandoObject
एक साधारण वर्ग है जो आपको सदस्यों को एक उदाहरण में जोड़ने और dynamic
सहयोगी का उपयोग करने की अनुमति देता है ।
DynamicObject
एक अधिक उन्नत कार्यान्वयन है जिसे आसानी से अनुकूलित व्यवहार प्रदान करने के लिए विरासत में मिला जा सकता है।
मैं इस प्रश्न का स्पष्ट उत्तर देने का प्रयास करूंगा, ताकि स्पष्ट रूप से समझाया जा सके कि गतिशील ExpandoObject
और , के बीच क्या अंतर हैं DynamicObject
।
बहुत जल्दी, dynamic
एक खोजशब्द है। यह एक प्रकार प्रति-से नहीं है। यह एक खोजशब्द है जो संकलक को डिज़ाइन-समय पर स्थैतिक प्रकार की जाँच को अनदेखा करने और इसके बजाय रन-टाइम पर लेट-बाइंडिंग का उपयोग करने के लिए कहता है। तो हम dynamic
इस उत्तर के बाकी हिस्सों में ज्यादा समय नहीं बिताएंगे ।
ExpandoObject
और DynamicObject
वास्तव में प्रकार हैं। सर्फ़ पर, वे एक-दूसरे के समान दिखते हैं। दोनों वर्ग लागू करते हैं IDynamicMetaObjectProvider
। हालांकि, गहरी खुदाई करें और आप पाएंगे कि वे समान नहीं हैं।
डायनामिकऑब्जेक्ट IDynamicMetaObjectProvider
विशुद्ध रूप से डेवलपर्स के लिए एक प्रारंभिक कार्यान्वयन है, जो डायनेमिक प्रेषण कार्य करने के लिए कस्टम अंतर्निहित भंडारण और पुनर्प्राप्ति व्यवहार के साथ गतिशील प्रेषण का समर्थन करने वाले अपने स्वयं के कस्टम प्रकारों को लागू करने के लिए एक प्रारंभिक बिंदु है।
संक्षेप में, डायनेमिकऑब्जेक्ट का उपयोग तब करें जब आप अपने खुद के प्रकार बनाना चाहते हैं जो डीएलआर के साथ उपयोग किए जा सकते हैं और जो भी कस्टम व्यवहार आप चाहें, उसके साथ काम कर सकते हैं।
उदाहरण: कल्पना कीजिए कि आप एक डायनामिक प्रकार लेना चाहते हैं जो कस्टम डिफॉल्ट लौटाता है जब भी किसी ऐसे सदस्य पर प्रयास किया जाता है जो मौजूद नहीं है (यानी रन टाइम में जोड़ा नहीं गया है)। और वह डिफ़ॉल्ट कहेगा, "मुझे क्षमा करें, इस जार में कुकीज़ नहीं हैं!"। यदि आप एक डायनामिक ऑब्जेक्ट चाहते हैं जो इस तरह का व्यवहार करता है, तो आपको नियंत्रित करने की आवश्यकता होगी कि जब कोई फ़ील्ड नहीं मिलती है तो क्या होता है। 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
एक सहायक आधार है जो अद्वितीय गतिशील व्यवहार के साथ अपने स्वयं के प्रकारों को सरल और आसान लागू करता है।
एक उपयोगी ट्यूटोरियल जिस पर ऊपर दिए गए उदाहरण स्रोत का बहुत कुछ आधारित है।
DynamicObject
: जब ओवरराइडिंग TryGetMember
, यदि आप झूठे वापस करते हैं तो RuntimeBinderException
गैर-मौजूदा संपत्ति तक पहुंचने की कोशिश करते समय फेंक दिया जाएगा। स्निपेट के लिए वास्तव में काम करने के लिए आपको वापस लौटना चाहिए true
।
C के अनुसार # भाषा विनिर्देश dynamic
एक प्रकार की घोषणा है। Ie का dynamic x
अर्थ है कि चर x
का प्रकार है dynamic
।
DynamicObject
एक प्रकार है जो इसे लागू करना आसान बनाता है IDynamicMetaObjectProvider
और इस प्रकार प्रकार के लिए विशिष्ट बाध्यकारी व्यवहार को ओवरराइड करता है।
ExpandoObject
एक प्रकार है जो प्रॉपर्टी बैग की तरह काम करता है। यानी आप रनटाइम के दौरान इस प्रकार के डायनेमिक इंस्टेंस के गुण, तरीके और इसके आगे जोड़ सकते हैं।
dynamic
एक वास्तविक प्रकार नहीं है ... यह संकलक को इस चर के लिए देर से बाध्यकारी का उपयोग करने के लिए बताने के लिए सिर्फ एक संकेत है। dynamic
चर वास्तव object
में MSIL के रूप में घोषित किए जाते हैं
उपरोक्त उदाहरण DynamicObject
स्पष्ट रूप से अंतर नहीं बताता है, क्योंकि यह मूल रूप से कार्यक्षमता को लागू कर रहा है जो पहले से ही प्रदान किया गया है ExpandoObject
।
नीचे दिए गए दो लिंक में, यह बहुत स्पष्ट है कि इसकी मदद से DynamicObject
वास्तविक प्रकार ( XElement
नीचे दिए गए लिंक में उपयोग किए गए उदाहरण में) को संरक्षित / परिवर्तित करना और गुणों और विधियों पर बेहतर नियंत्रण करना संभव है।
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;
}
}
}