Click here to Skip to main content
12,893,131 members (62,274 online)
Click here to Skip to main content
Add your own
alternative version


102 bookmarked
Posted 28 May 2010

DeepObject: A Multi-level C# 4.0 Dynamic Object

, 15 Oct 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
A class to create multi-level dynamic objects in C# 4.0


So, we all know now that C# came with the capability of having dynamic objects. We all know it came also with the nice ExpandoObjetc class that permits you to use those capabilities in a very easy and straightforward way. But what happens when you want to use a multi-level dynamic object?

Let me elaborate it a bit more. Simply speaking, the normal objects you use regularly are non-dynamic objects, meaning that the compiler uses the early-binding behavior by which it checks that the object's properties and methods exist at compile time. So, with them, if you use a property or a method that don’t exist in the class definition, your code won’t compile.

But when you use the new dynamic keyword to declare an object, you are instructing the compiler to use a late-binding mechanism, by which all those checks are postponed until run-time. In other words, when using a dynamic "type", the compiler understands that the actual type of the object is not going to be known until run-time, and that only then it is valid to perform the actual binding.

The nicest thing is that when the actual object used inherits from DynamicObject, or if it implements the IDynamicMetaObjectProvider interface, then you are allowed to intercept this late-binding mechanism and tell back the DLR (the dynamic analogous of the CLR) the way you want to deal when accessing those properties, or invoking those methods, that didn't exist in the class definition. For instance, a popular way is by by accessing a dictionary where to store the values of the properties along with their names, etc. (actually, this is pretty much what the ExpandoObject does).

Now, what if you want one of those dynamic properties to be a dynamic one itself? I mean one that is able to have its own set of second-level dynamic properties? So what happens if you want to use the following code?:

dynamic employee = new ...;
employee.Id = "007";
employee.Name.FirstName = "James";
employee.Name.FamilyName = "Bond";

The above scenario is not supported by any object I was aware of. On top of that, I wanted such an object to be serializable (so serializing whatever arbitrary contents it may hold), and disposable (so that I can guarantee no references to any object are kept if I invoke its Dispose() method).

There is no limit in the depth of the dynamic structure you are creating. And, of course, no restrictions at all to the type of values you can set into any of those dynamically created properties. Finally, you can also use indexes to create and access some properties, as we can see in the next example:

employee.Address[0] = "MI-5";
employee.Address[1] = "London";
employee.Address[2] = "United Kingdom";

You can use as many indexes, and of whatever types, as you need. Yes, a given index can have a null value as well. The only restriction is that the indexes list cannot be empty (which, by the way, mimics the restriction the C# compiler imposes).

DeepObject’s basics

DeepObject inherits from DynamicObject, and overrides its TryGetXXX() methods to permit the interception of the dynamic bindings. Internally it maintains a list of members where the new dynamic properties are stored, each of them being its own instance of DeepObject.

And this is the key fact: in this recursive way each of them are able to store either contents, to use them as regular dynamic properties to get or set these contents, or storing its own set of second-level dynamic properties. The TryGetXXX() methods are overridden in such a way that deal with all the complexities on your behalf.

DeepObject instances have just one major property: Deep, of type DeepCarrier. Its mission is to store all the internal details without polluting your dynamic instance with methods and properties, and by using it you can get access to a more advanced manipulation of your DeepObject instances. Deep has itself the following set of properties and methods:

  • The Members property permits the enumeration over the list of dynamic members. As expected, the Count property returns the number of members the instance has – note that this count only reflects its direct members, not the nth-level members it may conceptually have.
  • The idea is to let you use the dynamic syntax capabilities, as in the example, to automatically add the members you will need. But, if for whatever reason you need to add manually a member, instead of performing a dynamic binding you can do so by using any of the AddMember() methods. You can also remove a member using the RemoveMember() method, or clear all members by using the Clear() method.
  • Sometimes is useful to refer to a given member by the index in which it is stored in the internal list. To obtain this index you can use the IndexOf() method.
  • Its Name property returns the name used for this instance when it was dynamically created. Note also that you can give a name to these instances when you create them by using their constructors, something I found useful in some circumstances. If a given instance is hosted into another one, its FullName property returns the concatenation with dots of the full name of its parent plus its own given name, in a recursive way.
  • Note that when this member is an indexed one, its name is assigned automatically by using a deterministic algorithm (that basically concatenates the values of the indexes used to instantiate this member).
  • It is obvious that two members cannot share the same name, and the default behavior is to perform this comparison using a case-sensitive comparison. But you can set the mode to be case-insensitive by using the appropriate parameter in the constructor. In this case, this setting is propagated also to any child member is automatically created by the dynamic binding mechanism. You can get this setting by using the CaseSensitiveNames property.
  • Also, it may happen that at a given moment in time you may want to block the object’s structure, so not allowing to add any more members or remove any of them. You can get or set this behavior by using the Sealed property.
  • You can also get what value this member store, by using its Value property. If no value has been assigned to it, it returns null by default. You can find out if a value has been assigned to it or not in its HasValue property. Also, you can clean the value (meaning that HasValue will return false again) by using the ResetValue() method.
  • IsIndex will return true if the member is an indexed one, or false otherwise. An indexed member is one that requires an index, or several ones, to access it.
  • Host will return the hosting instance of this one as a member, or null if it has no parent (it is a standalone instance and not a member of anyone).
  • Level will return the level of this object: cero if it is not a member of anyone, 1 if it is a first-level member, 2 if it is a second-level member, and so on.


  • In this version I have dropped support for dynamic multi-level methods, because I have never end up using them. But if this causes a major problem, it won’t be hard to include them again, just let me know.


  • [v3, August 2012]: cleaner architecture and performance improvements. Dropped support for dynamic methods.
  • [v2, October 2010]: new methods and features added.
  • [v1, May 2010]: initial version.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Moises Barba
Spain Spain
Moises Barba has worked as CIO and CTO for some start-ups, and as Consulting Director for some major multinational IT companies. Solving complex puzzles and getting out of them business value has ever been among his main interests - that's why he has spent his latest 20 years trying to combine his degree in Theoretical Physics and his System Engineer MCSE with his MBA... and he is still trying to figure out how all these things can fit together. Even if flying a lot across many countries, along with the long working days that are customary in IT management and Consultancy, he can say that, after all, he lives in Spain (at least the weekends).

You may also be interested in...

Comments and Discussions

AnswerRe: My vote of 5 Pin
Moises Barba15-Oct-12 5:02
memberMoises Barba15-Oct-12 5:02 
Hello and thanks for your message.

No, DeepObject does not currently support INotifyPropertyChanged: I have not yet figure out a nice syntax that could be used in a "multi-level" environment, as it is the use case that DeepObject was designed for.

By "multi-level dynamic object" I mean that its first-level properties can also be dynamic (DeepObject) ones, and so they could carry their own second-level dynamic properties, that in turn could carry their own third level... and so forth, permitting to add and use them in a dynamic, natural and on-demand fashion.

It does already support other interfaces (ISerializable, ICloneable, IDisposable), so I will be happy to implement INotifyPropertyChanged if there is any suggestion on what would be the most handy sintax to use this feature afterwards.

Thanks, Moises
GeneralMy vote of 4 Pin
bartolo3-Sep-12 5:25
memberbartolo3-Sep-12 5:25 
GeneralRe: My vote of 4 Pin
Moises Barba25-Sep-12 20:48
memberMoises Barba25-Sep-12 20:48 
GeneralMy vote of 5 Pin
visalia2-Sep-12 8:04
membervisalia2-Sep-12 8:04 
GeneralRe: My vote of 5 Pin
Moises Barba25-Sep-12 20:48
memberMoises Barba25-Sep-12 20:48 
GeneralMy vote of 5 Pin
mbsmbs30-Aug-12 5:01
membermbsmbs30-Aug-12 5:01 
GeneralRe: My vote of 5 Pin
Moises Barba30-Aug-12 7:07
memberMoises Barba30-Aug-12 7:07 
AnswerReally a bit basic and out of date Pin
Clifford Nelson29-Aug-12 13:47
memberClifford Nelson29-Aug-12 13:47 
GeneralRe: Really a bit basic Pin
Moises Barba29-Aug-12 13:50
memberMoises Barba29-Aug-12 13:50 
GeneralRe: Really a bit basic Pin
Clifford Nelson30-Aug-12 6:27
memberClifford Nelson30-Aug-12 6:27 
GeneralMessage Automatically Removed Pin
15-Apr-11 8:58
groupglory44415-Apr-11 8:58 
GeneralAmazing Pin
japp2710-Dec-10 7:45
memberjapp2710-Dec-10 7:45 
GeneralRe: Amazing Pin
mbarbac10-Dec-10 21:19
membermbarbac10-Dec-10 21:19 
GeneralRe: Amazing Pin
wonderdelight18-Jan-11 3:36
memberwonderdelight18-Jan-11 3:36 
Generalerror Pin
John Giblin15-Nov-10 17:36
memberJohn Giblin15-Nov-10 17:36 
GeneralRe: error Pin
mbarbac17-Nov-10 1:40
membermbarbac17-Nov-10 1:40 
GeneralRe: error Pin
John Giblin18-Nov-10 12:32
memberJohn Giblin18-Nov-10 12:32 
GeneralMy vote of 3 Pin
Bilal Haider27-Oct-10 22:27
memberBilal Haider27-Oct-10 22:27 
Generalbinding Pin
cqwydz17-Oct-10 7:19
membercqwydz17-Oct-10 7:19 
GeneralRe: binding Pin
mbarbac18-Oct-10 12:05
membermbarbac18-Oct-10 12:05 
GeneralDynamic Objects and Why.... Pin
xzz019515-Oct-10 3:30
memberxzz019515-Oct-10 3:30 
GeneralRe: Dynamic Objects and Why.... Pin
Ankush Bansal14-Oct-12 23:56
memberAnkush Bansal14-Oct-12 23:56 
Generalok article Pin
Donsw31-May-10 17:44
memberDonsw31-May-10 17:44 
GeneralRe: ok article Pin
Dmitri Nesteruk6-Jun-10 6:29
memberDmitri Nesteruk6-Jun-10 6:29 
GeneralVery useful Pin
Bill Seddon31-May-10 14:22
memberBill Seddon31-May-10 14:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170424.1 | Last Updated 15 Oct 2012
Article Copyright 2010 by Moises Barba
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid