Так как я написал статью MSDN, на которую вы ссылаетесь, думаю, я должен ответить на нее.
Во-первых, я ожидал этого вопроса, и поэтому я написал сообщение в блоге, в котором показан более или менее реальный вариант использования ExpandoObject: Dynamic в 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;
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
.
d.MyEvent = null;
, или нет?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
я нахожу это более читабельным, но ymmv. И учитывая, что он статически типизирован, он более полезен в этом контексте.Одно преимущество - для обязательных сценариев. Сетки данных и сетки свойств будут подбирать динамические свойства через систему TypeDescriptor. Кроме того, привязка данных WPF будет понимать динамические свойства, поэтому элементы управления WPF могут связываться с ExpandoObject более легко, чем словарь.
Совместимость с динамическими языками, которые будут ожидать свойства DLR, а не словарные записи, также может рассматриваться в некоторых сценариях.
источник
List<dynamic>
иIEnumerable<dynamic>
использовать WPF4Для меня реальная выгода - это простое связывание данных из XAML:
...
...
источник
Взаимодействие с другими языками, основанными на
DLR
1-й причине, о которой я могу думать. Вы не можете передать их,Dictionary<string, object>
поскольку это неIDynamicMetaObjectProvider
. Еще одним дополнительным преимуществом является то, что он реализует,INotifyPropertyChanged
что означает, что в мире привязки данных WPF он также имеет дополнительные преимущества помимо того, чтоDictionary<K,V>
может предоставить вам.источник
Все дело в удобстве программиста. Я могу представить написание быстрых и грязных программ с этим объектом.
источник
Я думаю, что это будет иметь синтаксическое преимущество, поскольку вы больше не будете «подделывать» динамически добавленные свойства с помощью словаря.
Это и взаимодействие с динамическими языками, я думаю.
источник
Это пример из отличной статьи MSDN об использовании ExpandoObject для создания динамических специальных типов для входящих структурированных данных (например, XML, Json).
Мы также можем назначить делегата динамическому свойству ExpandoObject :
Таким образом, это позволяет нам вводить некоторую логику в динамический объект во время выполнения. Следовательно, вместе с лямбда-выражениями, замыканиями, динамическим ключевым словом и классом DynamicObject мы можем ввести некоторые элементы функционального программирования в наш код C #, которые мы знаем по динамическим языкам как JavaScript или PHP.
источник
В некоторых случаях это удобно. Я буду использовать его, например, для модульной оболочки. Каждый модуль определяет свой собственный диалог конфигурации, связанный с его настройками. Я предоставляю ему ExpandoObject в качестве Datacontext и сохраняю значения в моей конфигурации Storage. Таким образом, средство записи диалогового окна конфигурации просто привязывается к значению, и оно автоматически создается и сохраняется. (И предоставлены модулю для использования этих настроек, конечно)
Это просто проще в использовании, чем словарь. Но каждый должен знать, что внутренне это просто словарь.
Это похоже на LINQ, только синтаксический сахар, но иногда это облегчает ситуацию.
Поэтому, чтобы ответить на ваш вопрос напрямую: легче писать и легче читать. Но технически это, по сути, является
Dictionary<string,object>
(Вы можете даже привести его к одному, чтобы перечислить значения).источник
Я думаю, что это работает только потому, что у всего есть ToString (), в противном случае вам нужно будет знать, какой это был тип, и привести «объект» к этому типу.
Некоторые из них полезны чаще, чем другие, я пытаюсь быть тщательным.
Может быть гораздо более естественным получить доступ к коллекции, в данном случае к «словарю», используя более прямую точечную запись.
Кажется, что это можно использовать как действительно хороший Tuple. Вы по-прежнему можете называть своих членов "Item1", "Item2" и т. Д. ... но теперь вам не нужно, это также изменчиво, в отличие от Tuple. Это имеет огромный недостаток отсутствия поддержки intellisense.
Вам может быть неудобно с «именами элементов в виде строк», как и со словарем, вы можете чувствовать, что это слишком похоже на «выполнение строк», и это может привести к кодированию соглашений об именах и работе с морфемами и слоги, когда код пытается понять, как использовать члены :-P
Можете ли вы присвоить значение самому ExpandoObject или только его членам? Сравните и сопоставьте с динамическим / динамическим [], используйте тот, который больше соответствует вашим потребностям.
Я не думаю, что dynamic / dynamic [] работает в цикле foreach, вы должны использовать var, но, возможно, вы можете использовать ExpandoObject.
Вы не можете использовать динамический как элемент данных в классе, возможно, потому что это по крайней мере похоже на ключевое слово, возможно, вы можете использовать с ExpandoObject.
Я ожидаю, что это «ExpandoObject», может быть полезно для маркировки очень общих вещей, с кодом, который различается на основе типов, где используется много динамических вещей.
Будет хорошо, если вы сможете развернуть несколько уровней одновременно.
Это не лучший пример, представьте себе элегантное использование в ваших собственных проектах.
Жаль, что вы не можете заставить код построить некоторые из них и подтолкнуть результаты к intellisense. Я не уверен, как это будет работать, хотя.
Будьте хороши, если они могут иметь ценность, а также членов.
источник
После valueTuples, что за класс ExpandoObject? это 6 строк кода с ExpandoObject:
можно записать в одну строку с кортежами:
кроме того, с синтаксисом кортежа у вас есть строгий вывод типа и поддержка intlisense
источник