What are the true benefits of ExpandoObject?

143,102

Solution 1

Since I wrote the MSDN article you are referring to, I guess I have to answer this one.

First, I anticipated this question and that's why I wrote a blog post that shows a more or less real use case for ExpandoObject: Dynamic in C# 4.0: Introducing the ExpandoObject.

Shortly, ExpandoObject can help you create complex hierarchical objects. For example, imagine that you have a dictionary within a dictionary:

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

The deeper the hierarchy, the uglier the code. With ExpandoObject, it stays elegant and readable.

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

Second, as was already pointed out, ExpandoObject implements INotifyPropertyChanged interface which gives you more control over properties than a dictionary.

Finally, you can add events to ExpandoObject like here:

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

Also, keep in mind that nothing is preventing you from accepting event arguments in a dynamic way. In other words, instead of using EventHandler, you can use EventHandler<dynamic> which would cause the second argument of the handler to be dynamic.

Solution 2

One advantage is for binding scenarios. Data grids and property grids will pick up the dynamic properties via the TypeDescriptor system. In addition, WPF data binding will understand dynamic properties, so WPF controls can bind to an ExpandoObject more readily than a dictionary.

Interoperability with dynamic languages, which will be expecting DLR properties rather than dictionary entries, may also be a consideration in some scenarios.

Solution 3

The real benefit for me is the totally effortless data binding from XAML:

public dynamic SomeData { get; set; }

...

SomeData.WhatEver = "Yo Man!";

...

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

Solution 4

Interop with other languages founded on the DLR is #1 reason I can think of. You can't pass them a Dictionary<string, object> as it's not an IDynamicMetaObjectProvider. Another added benefit is that it implements INotifyPropertyChanged which means in the databinding world of WPF it also has added benefits beyond what Dictionary<K,V> can provide you.

Solution 5

It's all about programmer convenience. I can imagine writing quick and dirty programs with this object.

Share:
143,102
Reed Copsey
Author by

Reed Copsey

CTO - C Tech Development Corp. Microsoft .NET MVP - 2010-2019 I've been programming professionally for over 20 years, most recently with a focus on F#, C++ and C#.

Updated on February 03, 2022

Comments

  • Reed Copsey
    Reed Copsey over 2 years

    The ExpandoObject class being added to .NET 4 allows you to arbitrarily set properties onto an object at runtime.

    Are there any advantages to this over using a Dictionary<string, object>, or really even a Hashtable? As far as I can tell, this is nothing but a hash table that you can access with slightly more succinct syntax.

    For example, why is this:

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

    Really better, or substantially different, than:

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

    What real advantages are gained by using ExpandoObject instead of just using an arbitrary dictionary type, other than not being obvious that you're using a type that's going to be determined at runtime.

  • Reed Copsey
    Reed Copsey over 14 years
    Interesting. Thanks for the info re: events. That was a new one for me.
  • Alexandra Rusina
    Alexandra Rusina over 14 years
    @ Reed Yes, events are not yet documented for ExpandoObject. This particular example actually came up in the discussion on the blog. I will probably add it to documentation later.
  • Phil
    Phil about 13 years
    @J. Hendrix, do not forget that he also said "dirty". Intellisense has its downside, however, it makes debuggging and bug-catching easier. I personally still prefer static over dynamic types unless I am deal with a weird (and always rare) case.
  • Shimmy Weitzhandler
    Shimmy Weitzhandler over 12 years
    @AlexandraRusina, how does it know it's an event when you say d.MyEvent = null;, Or it doesn't?
  • Jalal
    Jalal almost 12 years
    @Shimmy i think it's just a place holder for events or any type of property.
  • Sergey Berezovskiy
    Sergey Berezovskiy over 11 years
    Maybe I'm missing something, but this is not event - this is a simple property of delegate type.
  • surfmuggle
    surfmuggle about 11 years
    It seems that databinding to dynamic objects is broken. The reporting user eisenbergeffect is here on SO and coordinator of caliburn.micro. @AlexandraRusina can you comment on the state of the bug and the status "Won't fix"
  • Royi Namir
    Royi Namir almost 11 years
    I believe it should be MyDelegate and not MyEvent.
  • supercat
    supercat over 10 years
    The ExpandoObject used with dynamic looks pretty much like the VB.NET "!" syntax for properties with a string-type indexer, aside from using "." rather than "!" (in vb.net, Foo!Biz!Baz.St is equivalent to Foo["Biz"]["Baz"].St); for some applications I took to using the VB style back before Expando-Object existed (I use a dot rather than !` on the last layer to allow it to be strongly typed). What differences do you see between dynamic+Expando-Object and the VB style "!"?
  • nawfal
    nawfal over 10 years
    +1 for convenience. However I find anonymous types can be equally convenient as a simple property bag and just better for its static-ness.
  • nawfal
    nawfal over 10 years
    The first block can be written using anonymous types: var expando = new { Address = new { State = "WA" } }; Console.WriteLine(expando.Address.State); I find this more readable but ymmv. And given it's statically typed, it's more useful in this context.
  • Tobias
    Tobias over 10 years
    I would not want to use it in production code, but it is very convenient in test-code and can make it look very beautiful.
  • Dr Blowhard
    Dr Blowhard over 9 years
    @nawfal thats not right - an anonymous is different to an Expando. You are creating an anonymous type, which can't then add arbitrary properties to.
  • nawfal
    nawfal over 9 years
    @SeanMill yes you're right about it. I just mean that "the given example" by the answerer can be better done using anonymous types. That is if all the properties are statically known. If you want to add properties dynamically, then you've to go the dictionary route again.
  • Graham Bass
    Graham Bass over 8 years
    For those curious, I am currently able to bind to List<dynamic> and IEnumerable<dynamic> using WPF4
  • Daniel Möller
    Daniel Möller about 7 years
    That's the javascript way of living :)
  • NetMage
    NetMage over 6 years
    Why not do a Dictionary<string,dynamic> instead of ExpandoObject for the root object, so the code for nested properties becomes just as easy: Console.WriteLine(dict["Address"]["State"]); ?
  • LxL
    LxL over 6 years
    Your examples are not identical in the sense that with value tuple, you cannot write T.c= 5; after finishing define T. With ExpandoObject you can do it because it's dynamic. Your example with value tuple is very identical with declaring anonymous type. E.g: var T2 = new { x = 1, y = 2, z = new { a = 3, b = 4 } };
  • Eng. M.Hamdy
    Eng. M.Hamdy over 6 years
    Why do I need to write T.c= 5 without defining it? ExpandoObject is only usefull when dealing with COM objects that are not defiend in .net. Otherwise, I neever use this ExpandoObject, because it is dirty and buggy in both design time and runtime.
  • LxL
    LxL over 6 years
    How about you have z at first assigned to (a:3,b:4) and then later you would like z to have additional c property? Can you do it with value tuple?
  • LxL
    LxL over 6 years
    So my point is that you cannot compare ExpandoObject with value tuple because they are designed for different purposes. By comparing your way, you dismissed the functionality which ExpandoObject is designed for, which is dynamic structure.