Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding members to a dynamic object at runtime

I am exploring the DynamicObject model in .NET 4.0. The application is one where an object will be described through some sort of text/xml file, and the program must create an object upon reading that file.

With DynamicObject, we can add members easily, given that we know the name of the member a priori. But, what if we don't even know the name of the member to add? Is there a way to make that dynamic as well?

For example, say I need to create an object with members 'Property1', 'Property2', and another object with 'PropertyA', and 'PropertyB' as described by the text/XML file. How can I create an object dynamically based on this info?

UPDATE I got some ideas from this post: http://www.codeproject.com/KB/cs/dynamicincsharp.aspx

This implementation allows me to do something like the following:

dynamic d = new PFDynamicChannel(); PFCouplings c = ((PFChannel)d).Coupling; d.NewProperty = "X"; 

The reason I do not wish to use a dictionary is to make use of TryGetMember, and TrySetMember methods that I can override, within which I can raise events that are essential for the program.

This way, I can inherit from a base class (PFChannel), but I can also add members on the fly. But, my problem is that I will not know the new property name until runtime. And, I actually don't think the dynamic object allows me to add new properties on the fly. If this is the case, how can I make use of ExpandoObject to give me this ability?

like image 530
sbenderli Avatar asked Oct 14 '10 14:10

sbenderli


People also ask

How to add new property in dynamic object c#?

To add a new property (or remove an existing one) you could override TryInvoke. When the mothod name is, for example, "AddProperty" and there is one argument of type string then you would add a new item in your dictionary with the name of the argument. Similarly you would dynamically define a "RemoveProperty" etc.

How to declare dynamic object in c#?

You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.

What is a dynamic model in c#?

In C# 4.0, a new type is introduced that is known as a dynamic type. It is used to avoid the compile-time type checking. The compiler does not check the type of the dynamic type variable at compile time, instead of this, the compiler gets the type at the run time.

What is an ExpandoObject?

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject. sampleMember instead of more complex syntax like sampleObject.


2 Answers

If you only need to do that, you should look at ExpandoObject. If you need to do that and still use DynamicObject, you will need to write code to remember property values, basically... which you could potentially do with an embedded ExpandoObject.

It's not clear to me what you want to do with this object afterwards though - are you sure you need dynamic typing at all? Would a Dictionary<string, object> actually be any worse? It depends what's going to consume the object later basically.

like image 119
Jon Skeet Avatar answered Sep 20 '22 22:09

Jon Skeet


According to this: Adding properties and methods to an ExpandoObject, dynamically!,

... you can use an expando object as your value holder, and cast it to an IDictionary<string, object> when you want to add dynamically named properties.

Example

dynamic myobject = new ExpandoObject();  IDictionary<string, object> myUnderlyingObject = myobject;  myUnderlyingObject.Add("IsDynamic", true); // Adding dynamically named property  Console.WriteLine(myobject.IsDynamic); // Accessing the property the usual way 

This is tested and will print out "true" on the console screen.

Of course, in your case, where your underlying object has to inherit from another class, this example is given just to give you an idea for a potential custom implementation.

Maybe including an expando object in your class implementation and redirecting calls to tryget and tryset to the instance of the expando object in your class?

UPDATE

IF your base class derives from DynamicObject (meaning you can override all TrySet/Get/Invoke methods) then, you could also use a dictionary internally. In the try get/set overrides you would do any event firing you want, and delegate the setting getting to the internal dictionary.

To add a new property (or remove an existing one) you could override TryInvoke. When the mothod name is, for example, "AddProperty" and there is one argument of type string then you would add a new item in your dictionary with the name of the argument. Similarly you would dynamically define a "RemoveProperty" etc. You don't even need an expando object.

class MyBaseClass: DynamicObject {     // usefull functionality }  class MyClass: MyBaseClass {     Dictionary<string, object> dynamicProperties = new Dictionary<string, object>();      override bool TryGetMember(...)     {        // read the value of the requested property from the dictionary        // fire any events and return     }      override bool TrySetMember(...)     {        // set the value of the requested property to the dictionary        // if the property does not exist,        // add it to the dictionary (compile time dynamic property naming)        // fire any events     }      override bool TryInvoke(...)     {        // check what method is requested to be invoked        // is it "AddProperty"??        // if yes, check if the first argument is a string        // if yes, add a new property to the dictionary        // with the name given in the first argument (runtime dynamic property naming)        // if there is also a second argument of type object,        // set the new property's value to that object.         // if the method to be invoked is "RemoveProperty"        // and the first argument is a string,        // remove from the Dictionary the property        // with the name given in the first argument.         // fire any events     } }  // USAGE static class Program {     public static void Main()     {         dynamic myObject = new MyClass();          myObject.FirstName = "John"; // compile time naming - TrySetMember         Console.WriteLine(myObject.FirstName); // TryGetMember          myObject.AddProperty("Salary");  // runtime naming (try invoke "AddProperty" with argument "Salary")         myObject.Salary = 35000m;         Console.WriteLine(myObject.Salary); // TryGetMember          myObject.AddProperty("DateOfBirth", new DateTime(1980,23,11)); // runtime naming (try invoke "AddProperty" with fisrt argument "DateOfBirth" and second argument the desired value)         Console.WriteLine(myObject.DateOfBirth); // TryGetMember          myObject.RemoveProperty("FirstName"); // runtime naming (try invoke "RemoveProperty" with argument "FirstName")          Console.WriteLine(myObject.FirstName); // Should print out empty string (or throw, depending on the desired bahavior) because the "FirstName" property has been removed from the internal dictionary.      } } 

Of course, as I said, that would work only if your base class Derives from DynamicObject.

like image 20
Thanasis Ioannidis Avatar answered Sep 21 '22 22:09

Thanasis Ioannidis