एक्सपेंडीओबजेक्ट के सही लाभ क्या हैं?


587

ExpandoObject वर्ग रनटाइम पर एक वस्तु पर .NET 4 आप मनमाने ढंग से सेट गुण के लिए अनुमति देता में जोड़ा जा रहा।

वहाँ एक का उपयोग करने के लिए इस पर कोई लाभ Dictionary<string, object>, या वास्तव में भी एक Hashtable हैं ? जहां तक ​​मैं बता सकता हूं, यह एक हैश टेबल के अलावा और कुछ नहीं है जिसे आप थोड़ा अधिक सक्सेना सिंटैक्स के साथ एक्सेस कर सकते हैं।

उदाहरण के लिए, यह क्यों है:

dynamic obj = new ExpandoObject();
obj.MyInt = 3;
obj.MyString = "Foo";
Console.WriteLine(obj.MyString);

वास्तव में बेहतर है, या काफी अलग है, की तुलना में:

var obj = new Dictionary<string, object>();
obj["MyInt"] = 3;
obj["MyString"] = "Foo";

Console.WriteLine(obj["MyString"]);

केवल एक मनमाना शब्दकोश प्रकार का उपयोग करने के बजाय एक्सपेंडीओबजेक्ट का उपयोग करके क्या वास्तविक लाभ प्राप्त किए जाते हैं, यह स्पष्ट नहीं होने के अलावा कि आप एक प्रकार का उपयोग कर रहे हैं जो रनटाइम पर निर्धारित होने जा रहा है।

जवाबों:


689

जब से मैंने MSDN लेख लिखा है, जिसका आप उल्लेख कर रहे हैं, मुझे लगता है कि मुझे इसका उत्तर देना होगा।

सबसे पहले, मैंने इस प्रश्न की आशंका जताई और इसीलिए मैंने एक ब्लॉग पोस्ट लिखी जिसमें एक्सपेंडीओबजेक्ट के लिए अधिक या कम वास्तविक उपयोग के मामले को दिखाया गया है: C # 4.0 में डायनामिक: एक्सपेंडीओऑबजेक्ट का परिचय

शीघ्र ही, ExpandoObject आपको जटिल पदानुक्रमित ऑब्जेक्ट बनाने में मदद कर सकता है। उदाहरण के लिए, कल्पना कीजिए कि आपके पास एक शब्दकोश है:

Dictionary<String, object> dict = new Dictionary<string, object>();
Dictionary<String, object> address = new Dictionary<string,object>();
dict["Address"] = address;
address["State"] = "WA";
Console.WriteLine(((Dictionary<string,object>)dict["Address"])["State"]);

गहरा पदानुक्रम है, बदसूरत कोड है। ExpandoObject के साथ यह सुरुचिपूर्ण और पठनीय रहता है।

dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);

दूसरा, जैसा कि यह पहले ही बताया गया था, एक्सपेंडीओबजेक्ट इम्प्लीमेंट्स इनोटिफ़प्रोपर्टी चेंजेड इंटरफ़ेस जो आपको एक शब्दकोश की तुलना में गुणों पर अधिक नियंत्रण देता है।

अंत में, आप यहां दिए गए ExpandoObject पर ईवेंट जोड़ सकते हैं:

class Program
{
   static void Main(string[] args)
   {
       dynamic d = new ExpandoObject();

       // Initialize the event to null (meaning no handlers)
       d.MyEvent = null;

       // Add some handlers
       d.MyEvent += new EventHandler(OnMyEvent);
       d.MyEvent += new EventHandler(OnMyEvent2);

       // Fire the event
       EventHandler e = d.MyEvent;

       e?.Invoke(d, new EventArgs());
   }

   static void OnMyEvent(object sender, EventArgs e)
   {
       Console.WriteLine("OnMyEvent fired by: {0}", sender);
   }

   static void OnMyEvent2(object sender, EventArgs e)
   {
       Console.WriteLine("OnMyEvent2 fired by: {0}", sender);
   }
}

इसके अलावा, ध्यान रखें कि कुछ भी आपको गतिशील तरीके से घटना के तर्क को स्वीकार करने से नहीं रोक रहा है। दूसरे शब्दों में, उपयोग करने के बजाय EventHandler, आप उपयोग कर सकते हैं EventHandler<dynamic>जिससे हैंडलर का दूसरा तर्क होगा dynamic


53
दिलचस्प। फिर से जानकारी के लिए धन्यवाद: घटनाओं। मेरे लिए वह नया था।
रीड कोपसे नोव

16
@AlexandraRusina, यह कैसे जानता है कि यह एक घटना है जब आप कहते हैं d.MyEvent = null;, या यह नहीं है?
शमी वेइटहैंडलर

20
शायद मुझे कुछ याद आ रहा है, लेकिन यह घटना नहीं है - यह प्रतिनिधि प्रकार की एक साधारण संपत्ति है।
सर्गेई बेरेज़ोवस्की

7
पहला ब्लॉक अनाम प्रकारों का उपयोग करके लिखा जा सकता है: var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);मुझे यह अधिक पठनीय लेकिन यमव लगता है। और यह सांख्यिकीय रूप से टाइप किया गया है, यह इस संदर्भ में अधिक उपयोगी है।
नवाफल

13
@nawfal सही नहीं है - एक अनाम एक विस्तारक के लिए अलग है। आप एक अनाम प्रकार बना रहे हैं, जो तब मनमाने गुण नहीं जोड़ सकते हैं।
डॉ ब्लरहार्ड 12-12

75

एक लाभ बाध्यकारी परिदृश्यों के लिए है। डेटा ग्रिड और प्रॉपर्टी ग्रिड टाइप डीस्क्रिप्ट सिस्टम के माध्यम से डायनामिक गुणों को उठाएगा। इसके अलावा, WPF डेटा बाइंडिंग गतिशील गुणों को समझेगा, इसलिए WPF नियंत्रण एक डिक्शनरी की तुलना में अधिक आसानी से एक ExpandoObject को बाँध सकता है।

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


6
ऐसा लगता है कि गतिशील वस्तुओं के लिए डेटाबाइंडिंग टूट गया है । रिपोर्टिंग उपयोगकर्ता eisenbergeffect SO और caliburn.micro के समन्वयक के यहाँ है। @AlexandraRusina आप बग और "स्थिति ठीक नहीं होगी" की स्थिति पर टिप्पणी कर सकते हैं
21

2
उन जिज्ञासुओं के लिए, मैं वर्तमान में WP174List<dynamic>IEnumerable<dynamic>
ग्राहम बास

47

मेरे लिए वास्तविक लाभ XAML से पूरी तरह से सहज डेटा बाइंडिंग है:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

 <TextBlock Text="{Binding SomeData.WhatEver}" />

28

अन्य भाषाओं के साथ इंटरॉप DLR# 1 कारण है जिसके बारे में मैं सोच सकता हूं। आप उन्हें पास नहीं कर सकते Dictionary<string, object>क्योंकि यह नहीं है IDynamicMetaObjectProvider। एक और जोड़ा लाभ यह है कि यह INotifyPropertyChangedWPF के डेटाबाइंडिंग दुनिया में इसका मतलब है कि यह भी Dictionary<K,V>आप क्या प्रदान कर सकते हैं परे लाभ जोड़ा गया है ।


19

यह सब प्रोग्रामर सुविधा के बारे में है। मैं इस वस्तु के साथ त्वरित और गंदे कार्यक्रम लिखने की कल्पना कर सकता हूं।


9
@जे। हेंड्रिक्स, यह मत भूलो कि उन्होंने "गंदा" भी कहा। Intellisense का अपना नकारात्मक पक्ष है, हालांकि, यह डीबगिंग और बग-कैचिंग को आसान बनाता है। जब तक मैं एक अजीब (और हमेशा दुर्लभ) मामले से निपटता हूं, तब तक मैं व्यक्तिगत रूप से गतिशील प्रकारों पर स्थिर रहना पसंद करता हूं।
फिल

सुविधा के लिए +1। हालांकि मुझे लगता है कि अनाम प्रकार एक साधारण संपत्ति बैग के रूप में समान रूप से सुविधाजनक हो सकते हैं और इसके स्थैतिक-नेस के लिए बेहतर है।
नवफाल

1
मैं इसे प्रोडक्शन कोड में इस्तेमाल नहीं करना चाहूंगा, लेकिन यह टेस्ट-कोड में बहुत सुविधाजनक है और यह बहुत सुंदर दिख सकता है।
टोबियास

14

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

मुझे लगता है कि गतिशील भाषाओं के साथ, और बीच में है।


11

यह आने वाले संरचित डेटा (यानी XML, Json) के लिए डायनामिक एड-हॉक प्रकार बनाने के लिए ExpandoObject का उपयोग करने के बारे में महान MSDN लेख से उदाहरण है ।

हम डेलीगेटऑबजेक्ट की डायनेमिक प्रॉपर्टी को भी सौंप सकते हैं:

dynamic person = new ExpandoObject();
person.FirstName = "Dino";
person.LastName = "Esposito";

person.GetFullName = (Func<String>)(() => { 
  return String.Format("{0}, {1}", 
    person.LastName, person.FirstName); 
});

var name = person.GetFullName();
Console.WriteLine(name);

इस प्रकार यह हमें कुछ तर्क को रनटाइम पर डायनेमिक ऑब्जेक्ट में इंजेक्ट करने की अनुमति देता है। इसलिए, लैम्ब्डा एक्सप्रेशन, क्लोजर, डायनामिक कीवर्ड और डायनामिक ऑबजेक्ट क्लास के साथ , हम कार्यात्मक प्रोग्रामिंग के कुछ तत्वों को अपने C # कोड में पेश कर सकते हैं, जिन्हें हम जावास्क्रिप्ट या PHP जैसी गतिशील भाषाओं से जानते हैं।


4

कुछ मामले हैं जहां यह आसान है। मैं उदाहरण के लिए एक मॉड्यूलर खोल के लिए इसका इस्तेमाल करूँगा। प्रत्येक मॉड्यूल यह परिभाषित करता है कि यह स्वयं का विन्यास है डायलॉग ने इसे सेटिंग्स पर डिटैबिट किया है। मैं इसे एक डिटैनेऑबजेक्ट के साथ प्रदान करता हूं क्योंकि यह डेटाकोटेक्स्ट है और मेरे कॉन्फ़िगरेशन स्टोरेज में वैल्यूज को सेव करता है। इस तरह कॉन्फ़िगरेशन डायलॉग लेखक को केवल एक मान पर बाँधना पड़ता है और यह स्वचालित रूप से बनाया और सहेजा जाता है। (और पाठ्यक्रम की इन सेटिंग्स का उपयोग करने के लिए मॉड्यूल को प्रदान किया गया)

यह केवल एक शब्दकोश की तुलना में उपयोग करने के लिए आसान है। लेकिन सभी को पता होना चाहिए कि आंतरिक रूप से यह सिर्फ एक शब्दकोश है।

यह LINQ की तरह सिर्फ सिंथैटिक शुगर है, लेकिन यह कभी-कभी चीजों को आसान बना देता है।

इसलिए सीधे अपने प्रश्न का उत्तर दें: यह लिखना आसान है और पढ़ना आसान है। लेकिन तकनीकी रूप से यह अनिवार्य रूप से एक है Dictionary<string,object>(आप इसे मूल्यों को सूचीबद्ध करने के लिए एक में भी डाल सकते हैं)।


-1
var obj = new Dictionary<string, object>;
...
Console.WriteLine(obj["MyString"]);

मुझे लगता है कि केवल इसलिए काम करता है क्योंकि सब कुछ एक ToString () है, अन्यथा आपको उस प्रकार को जानना होगा जो वह था और उस प्रकार के लिए 'ऑब्जेक्ट' डाल दिया।


इनमें से कुछ दूसरों की तुलना में अधिक उपयोगी हैं, मैं पूरी तरह से बनने की कोशिश कर रहा हूं।

  1. संग्रह को एक्सेस करना कहीं अधिक स्वाभाविक हो सकता है, इस मामले में अधिक प्रत्यक्ष डॉट नोटेशन का उपयोग करके प्रभावी रूप से एक "शब्दकोश" है।

  2. ऐसा लगता है जैसे यह एक बहुत अच्छा टपल के रूप में इस्तेमाल किया जा सकता है। आप अभी भी अपने सदस्यों को "आइटम 1", "आइटम 2" आदि कह सकते हैं ... लेकिन अब आपके पास नहीं है, यह टपल के विपरीत भी है। यह अंतर्मुखी समर्थन की कमी का बहुत बड़ा दोष है।

  3. "स्ट्रिंग्स के रूप में सदस्य के नाम" के साथ आप असहज हो सकते हैं, जैसा कि डिक्शनरी के साथ महसूस होता है, आप महसूस कर सकते हैं कि यह "स्ट्रिंग्स को निष्पादित करना" जैसा है, और इससे नामकरण सम्मेलनों को कोडित किया जा सकता है, और मैथेम के साथ काम करना और जब कोड यह समझने की कोशिश कर रहा है कि सदस्य कैसे उपयोग करें :-P

  4. क्या आप खुद को एक्सपेंडीओबजेक्ट के लिए मान प्रदान कर सकते हैं या सिर्फ इसके सदस्य हैं? डायनेमिक / डायनेमिक [] से तुलना करें और विपरीत करें, जो भी आपकी आवश्यकताओं के लिए सबसे उपयुक्त हो उसका उपयोग करें।

  5. मुझे नहीं लगता कि डायनेमिक / डायनेमिक [] एक फॉर्च लूप में काम करता है, आपको var का उपयोग करना होगा, लेकिन संभवतः आप ExpandoObject का उपयोग कर सकते हैं।

  6. आप कक्षा में डेटा सदस्य के रूप में गतिशील का उपयोग नहीं कर सकते, शायद इसलिए कि यह कम से कम एक कीवर्ड की तरह है, उम्मीद है कि आप एक्सपेंडेओवरजेक्ट के साथ कर सकते हैं।

  7. मुझे उम्मीद है कि यह "एक ExpandoObject है, कोड के साथ बहुत ही सामान्य चीजों को लेबल करने के लिए उपयोगी हो सकता है, कोड के साथ जो विभिन्न प्रकारों पर आधारित है जहां बहुत सारे गतिशील सामान का उपयोग किया जा रहा है।


अच्छा हो अगर आप एक साथ कई स्तरों को कम कर सकते हैं।

var e = new ExpandoObject();
e.position.x = 5;
etc...

यह सबसे अच्छा संभव उदाहरण नहीं है, अपने स्वयं के प्रोजेक्ट में उचित उपयोग की कल्पना करें।

यह शर्म की बात है कि आपके पास इनमें से कुछ का निर्माण नहीं हो सकता है और परिणामों को अंतर्मुखी करने के लिए धक्का दे सकता है। मुझे यकीन नहीं है कि हालांकि यह कैसे काम करेगा।

अच्छा हो अगर वे एक मूल्य के साथ ही सदस्य हो सकते हैं।

var fifteen = new ExpandoObject();
fifteen = 15;
fifteen.tens = 1;
fifteen.units = 5;
fifteen.ToString() = "fifteen";
etc...

-3

ValueTuples के बाद, ExpandOObject क्लास का क्या उपयोग है? इस 6 लाइनों कोड के साथ ExpandoObject:

dynamic T = new ExpandoObject();
T.x = 1;
T.y = 2;
T.z = new ExpandoObject();
T.z.a = 3;
T.b= 4;

tuples के साथ एक पंक्ति में लिखा जा सकता है:

var T = (x: 1, y: 2, z: (a: 3, b: 4));

ट्यूल सिंटैक्स के साथ-साथ आपके पास मजबूत प्रकार का इंट्रेंस और इंटलिसेंस सपोर्ट है


1
आपके उदाहरण इस अर्थ में समरूप नहीं हैं कि मूल्य के साथ, आप Tc = 5 नहीं लिख सकते हैं; टी। को परिभाषित करने के बाद विस्तारक के साथ आप इसे कर सकते हैं क्योंकि यह गतिशील है। अनाम प्रकार घोषित करने के साथ वैल्यू टपल के साथ आपका उदाहरण बहुत समान है। जैसे: var T2 = new {x = 1, y = 2, z = new {a = 3, b = 4}};
LxL

मुझे इसे परिभाषित किए बिना Tc = 5 लिखने की आवश्यकता क्यों है? ExtendedoObject केवल COM ऑब्जेक्ट्स के साथ काम करते समय उपयोगी है जो कि .net में डिफ़िंड नहीं होते हैं। अन्यथा, मैं इस एक्सपेंडीओबजेक्ट का उपयोग करता हूं, क्योंकि यह डिजाइन समय और रनटाइम दोनों में गंदा और छोटी गाड़ी है।
इंजी। M.Hamdy

1
कैसे के बारे में आप पहली बार (a: 3, b: 4) को सौंपा है और फिर बाद में आप चाहते हैं कि z आपके पास अतिरिक्त c संपत्ति है? क्या आप इसे वैल्यू टपल के साथ कर सकते हैं?
एलएक्सएल

इसलिए मेरा कहना है कि आप एक्सपेंडीओबजेक्ट की वैल्यू टपल से तुलना नहीं कर सकते क्योंकि वे अलग-अलग उद्देश्यों के लिए बनाए गए हैं। अपने तरीके की तुलना करके, आपने कार्यक्षमता को खारिज कर दिया, जो कि एक्सपेंडीओबजेक्ट के लिए डिज़ाइन किया गया है, जो गतिशील संरचना है।
एलएक्सएल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.