Вопрос

А ЭкспандоОбъект Добавленный в .NET 4 класс позволяет произвольно устанавливать свойства объекта во время выполнения.

Есть ли у этого преимущества перед использованием Dictionary<string, object>, или даже Хеш-таблица?Насколько я могу судить, это не что иное, как хеш-таблица, к которой вы можете получить доступ, используя немного более краткий синтаксис.

Например, почему это:

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> может вам предоставить.

Все дело в удобстве программиста. Я могу представить написание быстрых и грязных программ с этим объектом.

Я думаю, что это будет иметь синтаксическое преимущество, так как вы больше не будете " faking " динамически добавленные свойства с помощью словаря.

Это и взаимодействие с динамическими языками, я думаю.

Это пример из статьи MSDN об использовании ExpandoObject. для создания динамических специальных типов для входящих структурированных данных (например, XML, Json).

Мы также можем назначить делегата для динамического свойства ExpandoObject :

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 #, который мы знаем по динамическим языкам как JavaScript или PHP.

В некоторых случаях это удобно. Я буду использовать его, например, для модульной оболочки. Каждый модуль определяет свой собственный диалог конфигурации, связанный с его настройками. Я предоставляю ему ExpandoObject в качестве Datacontext и сохраняю значения в моей конфигурации Storage. Таким образом, средство записи диалогового окна конфигурации просто привязывается к значению, и оно автоматически создается и сохраняется. (И предоставляется модулю для использования этих настроек, конечно)

Это просто проще в использовании, чем словарь. Но все должны знать, что внутренне это просто словарь.

Это похоже на LINQ, просто синтаксический сахар, но иногда это облегчает ситуацию.

Итак, чтобы ответить на ваш вопрос напрямую: его легче писать и легче читать. Но технически это, по сути, Dictionary<string,object> (вы можете даже привести его к одному, чтобы перечислить значения).

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

Я думаю, что это работает только потому, что все имеет ToString (), в противном случае вам нужно будет знать, какой это был тип, и привести «объект» к этому типу.

<Ч>

Некоторые из них полезны чаще других, я стараюсь быть тщательным.

<Ол>
  • Может быть гораздо более естественным получить доступ к коллекции, в данном случае это фактически " словарь " с использованием более прямой нотации.

  • Кажется, это можно использовать как действительно хороший кортеж. Вы по-прежнему можете звонить своим членам & Quot; Item1 & Quot ;, & Quot; Item2 & Quot; и т.д ... но теперь вам не нужно, это также изменчиво, в отличие от Tuple. Это имеет огромный недостаток - отсутствие поддержки intellisense.

  • Вам может быть неудобно использовать " имена членов в виде строк " как и в случае со словарем, вы можете почувствовать, что это слишком похоже на " выполнение строк quot; и это может привести к кодированию соглашений об именах и работе с морфемами и слогами, когда код пытается понять, как использовать члены :-P

  • Можете ли вы присвоить значение самому ExpandoObject или только его членам? Сравните и сопоставьте с динамическим / динамическим [], используйте в зависимости от ваших потребностей.

  • Я не думаю, что dynamic / dynamic [] работает в цикле foreach, вам нужно использовать var, но, возможно, вы можете использовать ExpandoObject.

  • Вы не можете использовать динамический в качестве члена данных в классе, возможно, потому что это по крайней мере что-то вроде ключевого слова, возможно, вы можете использовать с ExpandoObject.

  • Я ожидаю, что это " is " ExpandoObject, может быть полезен для разметки очень общих вещей с помощью кода, который различается по типам, где используется много динамических вещей.

  • <Ч>

    Будьте хороши, если вы сможете развернуть несколько уровней одновременно.

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

    Это не лучший пример, представьте себе элегантное использование в ваших собственных проектах.

    Жаль, что вы не можете заставить код создавать некоторые из них и переводить результаты в intellisense. Я не уверен, как это будет работать.

    Будьте хороши, если они могут иметь как ценность, так и членов.

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

    кроме того, с синтаксисом кортежей у вас есть строгий вывод типов и поддержка intlisense

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top