سؤال

على ExpandoObject الدرجة التي تضاف إلى .صافي 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"]);

ما الحقيقي المزايا المكتسبة باستخدام ExpandoObject بدلا من مجرد استخدام التعسفي القاموس نوع آخر من عدم الواضح أن كنت تستخدم نوع التي سوف يتم تحديدها في وقت التشغيل.

هل كانت مفيدة؟

المحلول

منذ أن كتبت المقالة MSDN كنت تقصد أعتقد أن الإجابة على هذا واحد.

أولا توقعت هذا السؤال و هذا هو السبب في أنني كتبت بلوق وظيفة التي تظهر أكثر أو أقل واقعية استخدام حالة ExpandoObject: ديناميكية في C# 4.0:إدخال ExpandoObject.

قريبا 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 تنفذ INotifyPropertyChanged واجهة التي تمنحك المزيد من التحكم في خصائص من القاموس.

وأخيرا يمكنك إضافة الأحداث إلى 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;

       if (e != null)
       {
           e(d, new EventArgs());
       }

       // We could also fire it with...
       //      d.MyEvent(d, new EventArgs());

       // ...if we knew for sure that the event is non-null.
   }

   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);
   }
}

نصائح أخرى

ميزة واحدة هي الملزمة السيناريوهات.البيانات شبكات والممتلكات شبكات سوف تلتقط خصائص ديناميكية عبر TypeDescriptor النظام.وبالإضافة إلى ذلك, WPF ربط البيانات سوف تفهم الخصائص الديناميكية ، لذلك WPF ضوابط يمكن ربط ExpandoObject بسهولة أكثر القاموس.

التوافقية مع اللغات الديناميكية ، التي يتوقع DLR خصائص بدلا من إدخالات القاموس, كما يمكن النظر في بعض السيناريوهات.

الفائدة الحقيقية بالنسبة لي هي تماما دون عناء ربط البيانات من XAML:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

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

إمكانية التشغيل المتداخل مع لغات أخرى تأسست على DLR هو السبب رقم 1 يمكنني التفكير.لا يمكنك تمرير لهم Dictionary<string, object> كما انه ليس IDynamicMetaObjectProvider.آخر فائدة إضافية هي أن تنفذ INotifyPropertyChanged وهو ما يعني في ربط البيانات عالم WPF له أيضا فوائد إضافية تتجاوز ما Dictionary<K,V> يمكن أن توفر لك.

انها كل شيء عن مبرمج الراحة.يمكنني تخيل كتابة سريعة وقذرة البرامج مع هذا الكائن.

وأعتقد أنه سوف يكون لها فائدة نحوية ، حيث لن يكون "تزوير" بشكل حيوي إضافة خصائص باستخدام القاموس.

هذا و إمكانية التشغيل المتداخل مع اللغات الديناميكية أعتقد.

إنه مثال من رائع المقالة MSDN حول استخدام ExpandoObject لخلق ديناميكية مخصصة أنواع الواردة البيانات المهيكلة (أنا.هـ XML, Json).

يمكننا أيضا تعيين مندوب ExpandoObject's دينامية الملكية:

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);

وبالتالي فإنه يتيح لنا أن حقن بعض المنطق في كائن ديناميكي في وقت التشغيل.ولذلك ، جنبا إلى جنب مع تعبيرات لامدا, الإغلاق, ديناميكية الكلمة ، DynamicObject الدرجة, يمكننا إدخال بعض عناصر البرمجة الوظيفية في التعليمات البرمجية C#, ونحن يعلم من ديناميكية لغات مثل جافا سكريبت أو PHP.

هناك بعض الحالات التي يكون فيها هذا هو في متناول يدي.سوف استخدامه النمطي قذيفة على سبيل المثال.كل وحدة تعرف نفسها انها التكوين الحوار databinded إلى الإعدادات.أنا تزويدها ExpandoObject كما انها Datacontext وحفظ القيم في تكوين التخزين.هذه الطريقة في الحوار تكوين الكاتب فقط إلى ربط قيمة وانها إنشاؤه تلقائيا وحفظها.(و المقدمة إلى وحدة باستخدام هذه الإعدادات طبعا)

انها ببساطة أسهل استخداما من القاموس.ولكن يجب أن يكون الجميع على علم بأن داخليا هو فقط قاموس.

انها مثل LINQ فقط النحوية السكر ، ولكنه يجعل الأمور أسهل في بعض الأحيان.

لذا للإجابة على سؤالك مباشرة:أنه من الأسهل لكتابة و أسهل في القراءة.ولكن من الناحية الفنية أساسا Dictionary<string,object> (حتى يمكنك الزهر إلى قائمة القيم).

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

أعتقد أن هذا يعمل فقط لأن كل شيء له ToString(), وإلا عليك أن تعرف نوع أنه كان يلقي كائن إلى هذا النوع.


بعض هذه هي مفيدة أكثر من غيرها, أنا أحاول أن تكون شاملة.

  1. قد يكون أكثر بكثير من الطبيعية إلى مجموعة ، في هذه الحالة ما هو فعال "القاموس" ، وذلك باستخدام أكثر مباشرة تدوين نقطة.

  2. يبدو كما لو أن هذا يمكن حقا لطيفة Tuple.لا يزال يمكنك استدعاء أعضاء "Item1", "Item2" الخ...ولكن الآن لم يكن لديك ل ، كما أنها قابلة للتغيير ، على عكس Tuple.هذا لا يكون العيب ضخمة من عدم التحسس الدعم.

  3. قد يكون غير مريح مع "أسماء الأعضاء مثل السلاسل" ، كما هو يشعر مع القاموس ، قد يشعر أنه هو أيضا مثل "تنفيذ السلاسل" ، فإنه قد يؤدي إلى اصطلاحات التسمية الحصول على الأكواد في التعامل مع العمل مع الصرفية و المقاطع عندما الكود هو محاولة فهم كيفية استخدام أعضاء :-P

  4. يمكنك تعيين قيمة إلى ExpandoObject نفسها أو مجرد انها الأعضاء ؟ مقارنة مع ديناميكية/ديناميكية[], استخدام أيهما أفضل تناسب احتياجاتك.

  5. لا أعتقد الحيوي الديناميكي/[] يعمل في حلقة foreach, لديك لاستخدام فار, ولكن ربما يمكنك استخدام ExpandoObject.

  6. لا يمكنك استخدام ديناميكية عضو بيانات في الصف, ربما لأنه على الأقل كنوع من الكلمة ، نأمل يمكنك مع ExpandoObject.

  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...

بعد 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;

يمكن أن تكون مكتوبة في سطر واحد مع الصفوف:

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

إلى جانب مع tuple جملة لديك نوع قوي الاستدلال و intlisense الدعم

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top