Desde que escrevi o artigo do MSDN a que você está se referindo, acho que tenho que responder a este.
Primeiro, eu antecipei essa pergunta e foi por isso que escrevi uma postagem no blog que mostra um caso de uso mais ou menos real para o ExpandoObject: Dynamic no C # 4.0: Apresentando o ExpandoObject .
Em breve, o ExpandoObject pode ajudá-lo a criar objetos hierárquicos complexos. Por exemplo, imagine que você tenha um dicionário dentro de um dicionário:
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"]);
Quanto mais profunda é a hierarquia, mais feio é o código. Com o ExpandoObject, ele permanece elegante e legível.
dynamic expando = new ExpandoObject();
expando.Address = new ExpandoObject();
expando.Address.State = "WA";
Console.WriteLine(expando.Address.State);
Segundo, como já foi apontado, o ExpandoObject implementa a interface INotifyPropertyChanged, que oferece mais controle sobre propriedades do que um dicionário.
Por fim, você pode adicionar eventos ao ExpandoObject como aqui:
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);
}
}
Além disso, lembre-se de que nada o impede de aceitar argumentos de eventos de maneira dinâmica. Em outras palavras, em vez de usar EventHandler
, você pode usar o EventHandler<dynamic>
que causaria o segundo argumento do manipulador dynamic
.
d.MyEvent = null;
: Ou não?var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State);
acho isso mais legível, mas ymmv. E, dado que é digitado estaticamente, é mais útil nesse contexto.Uma vantagem é para cenários vinculativos. As grades de dados e grades de propriedades capturam as propriedades dinâmicas por meio do sistema TypeDescriptor. Além disso, a ligação de dados do WPF entenderá propriedades dinâmicas, portanto, os controles do WPF podem ser vinculados a um ExpandoObject mais facilmente que a um dicionário.
A interoperabilidade com idiomas dinâmicos, que espera propriedades de DLR em vez de entradas de dicionário, também pode ser considerada em alguns cenários.
fonte
List<dynamic>
eIEnumerable<dynamic>
usar o WPF4O benefício real para mim é a ligação de dados totalmente sem esforço do XAML:
...
...
fonte
A interoperabilidade com outras linguagens baseadas na
DLR
é a razão número 1 em que consigo pensar. Você não pode passar para elesDictionary<string, object>
porque não éIDynamicMetaObjectProvider
. Outro benefício adicional é que ele implementa, oINotifyPropertyChanged
que significa que, no mundo de ligação de dados do WPF, ele também oferece benefícios além do queDictionary<K,V>
pode lhe proporcionar.fonte
É tudo sobre a conveniência do programador. Eu posso imaginar escrever programas rápidos e sujos com esse objeto.
fonte
Eu acho que terá um benefício sintático, já que você não estará mais "fingindo" propriedades adicionadas dinamicamente usando um dicionário.
Isso e interage com linguagens dinâmicas, eu pensaria.
fonte
É um exemplo de excelente artigo do MSDN sobre o uso do ExpandoObject para criar tipos ad-hoc dinâmicos para dados estruturados de entrada (por exemplo, XML, Json).
Também podemos atribuir delegado à propriedade dinâmica do ExpandoObject :
Assim, permite injetar alguma lógica no objeto dinâmico em tempo de execução. Portanto, juntamente com expressões lambda, closures, palavra-chave dinâmica e classe DynamicObject , podemos introduzir alguns elementos de programação funcional em nosso código C #, que conhecemos de linguagens dinâmicas como JavaScript ou PHP.
fonte
Existem alguns casos em que isso é útil. Vou usá-lo para um shell modularizado, por exemplo. Cada módulo define seu próprio Diálogo de Configuração, vinculado às suas configurações. Eu forneço um ExpandoObject como Datacontext e salvo os valores em minha configuração Storage. Dessa forma, o gravador do Diálogo de Configuração precisa vincular-se a um Valor e é automaticamente criado e salvo. (E fornecido ao módulo para usar essas configurações, é claro)
É simplesmente mais fácil de usar do que um dicionário. Mas todos devem estar cientes de que internamente é apenas um dicionário.
É como o LINQ apenas açúcar sintático, mas às vezes facilita as coisas.
Portanto, para responder diretamente à sua pergunta: é mais fácil escrever e ler. Mas tecnicamente é essencialmente um
Dictionary<string,object>
(você pode até convertê-lo em um para listar os valores).fonte
Eu acho que só funciona porque tudo tem um ToString (), caso contrário você teria que saber o tipo que era e converter o 'objeto' para esse tipo.
Alguns deles são úteis com mais frequência do que outros, estou tentando ser minucioso.
Pode ser muito mais natural acessar uma coleção, nesse caso o que é efetivamente um "dicionário", usando a notação de ponto mais direta.
Parece que isso poderia ser usado como uma tupla realmente agradável. Você ainda pode chamar seus membros de "Item1", "Item2" etc ... mas agora você não precisa, também é mutável, ao contrário de uma Tupla. Isso tem a enorme desvantagem da falta de suporte do intellisense.
Você pode se sentir desconfortável com "nomes de membros como seqüências de caracteres", como é a sensação no dicionário, pode parecer que é muito parecido com "executar sequências" e pode levar a convenções de nomenclatura a serem codificadas e lidar com o trabalho com morfemas e sílabas quando o código está tentando entender como usar os membros :-P
Você pode atribuir um valor a um ExpandoObject em si ou apenas a seus membros? Compare e contraste com dinâmico / dinâmico [], use o que melhor se adapte às suas necessidades.
Eu não acho que dinâmico / dinâmico [] funcione em um loop foreach, você precisa usar var, mas possivelmente você pode usar ExpandoObject.
Você não pode usar dinâmico como membro de dados em uma classe, talvez porque seja pelo menos como uma palavra-chave, espero que você possa usar o ExpandoObject.
Espero que "seja" um ExpandoObject, possa ser útil rotular coisas muito genéricas, com código que se diferencia com base nos tipos em que há muitas coisas dinâmicas sendo usadas.
Seja legal se puder detalhar vários níveis ao mesmo tempo.
Esse não é o melhor exemplo possível, imagine usos elegantes, conforme apropriado, em seus próprios projetos.
É uma pena que você não possa fazer com que o código construa alguns deles e forneça os resultados ao intellisense. Não tenho certeza de como isso funcionaria.
Seja gentil se eles puderem ter um valor e também membros.
fonte
Após valueTuples, para que serve a classe ExpandoObject? este código de 6 linhas com ExpandoObject:
pode ser escrito em uma linha com tuplas:
além da sintaxe da tupla, você tem forte inferência de tipo e suporte a intlisense
fonte