Dynamic C# & DLR (Part IV): ExpandoObject Class

Intro

In the following tow articles I´ll try to explain the advantages of building your own custom dynamic types in certain scenarios. We will review the IDynamicMetadataObjectProvider interface and DynamicObject type and how we can use it for creating dynamic types for a more fluid code. In addition to creating custom dynamic types we can also use built-in ExpandoObject class for creating object over which we can add properties, method and events dynamically. This can be considered as general purpose dynamic class can be thinking to be similar to dictionary which usually will contain the member properties and where the keys are added dynamically. As DynamicObject does, ExpandoObject implements IDynamicMetadataObjectProvider interface;  let´s explore some of ExpandoObject possibilities:

ExpandoObject approach

I´ll start by providing the first approach by using ExpandoObject class. In order to show how we can make use of ExpandoObject let´s see following simple Main() method:

static void Main(string[] args)
        {
            dynamic person = new ExpandoObject();
 
            person.Details="person details";
            person.Name="David";
            person.Surname= "Checa";
            person.NIF="00000000P";
            person.Phone="615151515";
            // etc.....
 
            foreach (var prop in person)
                Console.WriteLine($"{prop.Key} : {prop.Value}");
 
            Console.ReadLine();
        }

We can iterate and manage as dictionary because ExpandoObject implements the following interfaces

public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable, INotifyPropertyChanged
    {
Etc…
    }
If we run this we obtain:

 

Dynamic C# ExpandoObject 1
Dynamic C# ExpandoObject 1

In addition to this approach we can also implement our Main() method in the following way

static void Main(string[] args)
        {
            dynamic person = new ExpandoObject();
 
            var dyn = (IDictionary<string,object>)person;
 
            dyn.Add("Name", "David");
            dyn.Add("Surname", "Checa");
            dyn.Add("NIF", "00000000P");
            dyn.Add("Phone", "615151515");
            dyn.Add("Details", "person details");
            //etc...
 
            foreach (var prop in person)
                Console.WriteLine($"{prop.Key} : {prop.Value}");
 
            Console.ReadLine();
        }

 

Here we see that before we need to apply specific IDictionary<string,object> casting before calling the Add() method, this is why this method is not directly provided by ExpandoObject. If we run this:

Dynamic C# ExpandoObject 2
Dynamic C# ExpandoObject 2

In addition to create properties dynamically we also can create methods and evens in the same way, let´s see some examples

ExpandoObject: Creating Methods Dynamically

It´s also possible add methods dynamically to ExpandoObject by using generic delegates. In the following sample we are going to create two methods dynamically; first one — Check () method — is a basic checking for Name and Surname person properties. The second one — Write () method –will use this checking for printing all person properties into screen. Finally we invoke Write() method :

static void Main(string[] args)
        {
            dynamic person = new ExpandoObject();
 
            person.Details = "person details";
            person.Name = "David";
            person.Surname = "Checa";
            person.NIF = "00000000P";
            person.Phone = "615151515";
            // etc.....
 
            person.Check = (Func<bool>)(() =>
            {
                // check if name and surname are populated
                if (string.IsNullOrWhiteSpace(person.Name) || string.IsNullOrWhiteSpace(person.Surname))
                    return false;
                else
                    return true;
            });
 
            person.Write = (Action)(() =>
            {
                if (person.Check())
                {
                    foreach (var prop in person)
                        Console.WriteLine($"{prop.Key} : {prop.Value}");
                }
            });
 
 
            person.Write();
 
            Console.ReadLine();
        }

If we run this we obtain

Dynamic C# ExpandoObject 3
Dynamic C# ExpandoObject 3

ExpandoObject: Creating Events Dynamically

Finally I´ll show how to define new event dynamically – PhoneChanged – over our target type. Let´s suppose we want to raise this event every time Phone property is updated, and write a console message in response informing about this change.

static void Main(string[] args)
        {
            dynamic person = new ExpandoObject();
 
            person.Details = "person details";
            person.Name = "David";
            person.Surname = "Checa";
            person.NIF = "00000000P";
            person.Phone = "615151515";
            // etc.....
 
            var dyn = (IDictionary<string, object>)person;
 
            dyn.Add("PhoneChanged", new Action<object, EventArgs>((sender, eventArgs) =>
            {
                dynamic pers = sender as ExpandoObject;
                var phoneArgs = eventArgs as PhoneChangedEventArgs;
                Console.WriteLine($"Event raised when updating person phone to : {phoneArgs?.Phone}");
                person.Phone = phoneArgs?.Phone;
            }));
 
            ((INotifyPropertyChanged)person).PropertyChanged +=
               new PropertyChangedEventHandler((sender, ea) =>
               {
                   dynamic exp = sender as dynamic;
                   var propEventArgs = ea as PropertyChangedEventArgs;
                   if (propEventArgs?.PropertyName == "Phone")
                       exp.PhoneChanged(exp, new PhoneChangedEventArgs() { Phone = exp.Phone});
               });
 
 
            person.Phone="610101010";
 
            Console.ReadLine();
        }

As can be seen, we take advantage from (IDictionary<string, object>) goodness in order to use Add method for adding new even; as second param we include the handler by using Action<object, EventArgs>. In Addition, ExpandoObject supports INotifyPropertyChanged that we will use in this case for hooking every change in Phone property

ExpandoObject: Deleting Dynamically

In addition to that we can use the (IDictionary<string, object>) casting for implementing member deleting. This way we can enhance features from statically approach of C#, something similar to

static void Main(string[] args)
        {
            dynamic person = new ExpandoObject();
 
            person.Name = "David";
            person.Surname = "Checa";
            person.NIF = "00000000P";
            person.Phone = "615151515";
            person.Details = "person details";
            // etc.....
 
            foreach (var prop in person)
                Console.WriteLine($"{prop.Key} : {prop.Value}");
 
 
            var dyn = (IDictionary<string, object>)person;
            dyn.Remove("Details");
 
            Console.WriteLine("\n\nAfter deleting member");
 
            foreach (var prop in person)
                Console.WriteLine($"{prop.Key} : {prop.Value}");
 
            Console.ReadLine();
        }

When we run the console, we obtain:

Dynamic C# ExpandoObject 4
Dynamic C# ExpandoObject 4

Additional Considerations

As we can see, ExpandoObject is a versatile and flexible built-in class that allows us to model wide range of scenarios. We can go further and create our custom dynamic types, which will be the next topic to be reviewed…

That´s all by now

See you on the road!