-
Notifications
You must be signed in to change notification settings - Fork 9
Expando
- Provide a dynamic behavior, so that, on the fly, new properties may be added to them without recompilation, just like in the dynamic languages like JavaScript or Python.
- Access their properties:
- directly, with the API defined by their class.
- by the means of the
dynamickeyword. - by their name, just like a dictionary.
Objects supporting settings or getting values by the mean of a string key implement the IIndexable interface.
It provides one single indexer:
-
this[key: string]: object. By this mean, the object may be used like a dictionary.
Dynamic expandable objects implement the IExpando interface, which is an abstraction and an extension of the .NET's Expando sealed class. To support conversion to dynamic, it inherits the IDynamicMetaObjectProvider interface. Additionally, it inherits the IIndexable interface, to allow setting or getting property values by their name.
Kephas provides through ExpandoBase a base implementation for expando objects. Objects inheriting from an ExpandoBase can be used either as a standalone object, or can wrap an existing instance or dictionary and expose it as a dynamic object.
To get or set a value from/to an ExpandoBase, based on the property name or key, the following steps are taken:
- First of all, it is tried to identify a property from the inner object, if one is set, by the provided name/key.
- The next try is to identify the property from the expando object itself.
- Lastly, if still a property by the provided name cannot be found, the inner dictionary is searched/updated by the provided key.
All the values from the expand can be collected in form a dictionary, using the ToDictionary() method. The values are added in their overwrite order:
- First of all, all the inner dictionary entries are added.
- Then, the property values in the current expand object are added or existing values overwritten.
- Lastly, the values from the inner object are added or existing values overwritten.
-
GetInnerObjectTypeInfo(): IRuntimeTypeInfo: returns the type information of the inner/wrapped object. If no wrapped object was provided, this returnsnull. -
GetThisTypeInfo(): IRuntimeTypeInfo: returns the type information of this expando. Override if, for some reason, another type information should be used than the one of the expando itself. -
TryGetValue(key: string, out value: object): boolean: Method used to get a value from the expando based on a property name or dictionary key. Override if a logic other than the default presented one should be used. -
TrySetValue(key: string, value: object): boolean: Method used to set a value from the expando based on a property name or dictionary key. Override if a logic other than the default presented one should be used.
A ready-to-use expando class is Expando. Upon initialization, a flag controls how the internal dictionary is used: thread safe or not. Depending on it, the inner dictionary is set to a ConcurrentDictionary or Dictionary.
dynamic expando = new Expando();
expando.Property = "value";
Assert.AreEqual("value", expando.Property); var dictionary = new Dictionary<string, object>();
dynamic expando = new Expando(dictionary);
expando.Property = "value";
Assert.AreEqual("value", dictionary["Property"]); public class Person : Expando
{
public int Age { get; set; }
}
//...
var person = new Person();
person.Age = 30; // the age is set through the class API
dynamic dynPerson = person;
dynPerson.Age = 23; // the age is set through the dynamic features
Assert.AreEqual(23, person.Age);
person["Age"] = 40;
Assert.AreEqual(40, person.Age);
dynPerson.IsOld = true;
Assert.IsTrue(person["IsOld"]); public class Contact
{
public string Name { get; set; }
}
//...
var contact = new Contact();
dynamic dynContact = new Expando(contact);
dynContact.Name = "John";
Assert.AreEqual("John", contact.Name);Expandos can be sucessfully used where a dynamic context is useful. Examples:
- Context objects, used to provide information about the current execution context, passed along the execution flow.
- Metadata objects, used to provide meta information about entities and other artifacts.
- Configuration settings.