Meta

Elastic Object Implementation in .NET

I think it was Anoop Madhusudanan (aka, amazedsaint) who first coined the term “Elastic Object”. He even built an implementation, which you can find on GitHub and NuGet, which is very nice. Basically, it’s a class that allows adding members to its instances dynamically; this is a widely known pattern in scripting languages such as JavaScript, but not so easy to implement in .NET.

Now, I wanted to have something like this but also add some custom features that were missing, so I started something from scratch – yes, for the good or for the bad, my code is totally different from amazedsaint’s). Of course, both leverage the dynamic type, that’s where the whole idea came from.

Here are some examples of what we can do:

dynamic obj = new ElasticObject();

obj.A = 1; //obj["A"] = 1;

obj.A.B = "1";

var props = TypeDescriptor.GetProperties(obj); //"A"

dynamic obj = new ElasticObject(new { A = 1 });

int i = obj.A;

int ni = ~obj.A;

int ii = --obj.A;

bool b = obj.A;

dynmic obj = new ElasticObject(1);

var clone = obj.Clone();

(obj as INotifyPropertyChanged).PropertyChanged += (s, e) => { };

dynamic obj = new ElasticObject();

obj.A = 1; //obj["A"] = 1;

obj.A.B = "1";

var path = obj.A.B["$path"]; //"A.B"

var parent = obj.A.B["$parent"]; //obj.A

var value = obj.A.B["$value"]; //"1"

var type = obj.A.B["$type"]; //string

Basically, I Inherit from DynamicObject and I use an internal dictionary for storing all dynamically assigned values, which will, in turn, be also ElasticObjects. I also allow for a “self value”, which will be the ElasticObject’s main value, in case no additional properties are supplied. I also provide implementations for some typical .NET interfaces, like INotifyPropertyChanged and ICloneable, and supply my own TypeDescriptionProvider which takes into account the dynamic properties and also a custom TypeConverter.

There are some provided properties that grant us access to the ElasticObject’s internals:

$Root: the root ElasticObject instance;

$Parent: the parent ElasticObject instance for the current one;

$Path: the full property path from the current object until the root;

$Value: the self value;

$Type: the type of the self value.

Without further discussion, here is the code for my ElasticObject class: