Dynamically add properties to a existing object

Viewed 140010

I create the person object like this.

 Person person=new Person("Sam","Lewis") 

It has properties like this.

person.Dob
person.Address

But now I want to add properties like this and set the values at the run time after creating the object. person.Age person.Sex

How can I add those extra properties after creating the object. Those property name can be changed time to time. Therefor can't hardcode the "Age" and "Sex".

8 Answers

If you only need the dynamic properties for JSON serialization/deserialization, eg if your API accepts a JSON object with different fields depending on context, then you can use the JsonExtensionData attribute available in Newtonsoft.Json or System.Text.Json.

Example:

public class Pet
{
    public string Name { get; set; }
    public string Type { get; set; }

    [JsonExtensionData]
    public IDictionary<string, object> AdditionalData { get; set; }
}

Then you can deserialize JSON:

public class Program
{
    public static void Main()
    {
        var bingo = JsonConvert.DeserializeObject<Pet>("{\"Name\": \"Bingo\", \"Type\": \"Dog\", \"Legs\": 4 }");
        Console.WriteLine(bingo.AdditionalData["Legs"]);        // 4

        var tweety = JsonConvert.DeserializeObject<Pet>("{\"Name\": \"Tweety Pie\", \"Type\": \"Bird\", \"CanFly\": true }");
        Console.WriteLine(tweety.AdditionalData["CanFly"]);     // True

        tweety.AdditionalData["Color"] = "#ffff00";

        Console.WriteLine(JsonConvert.SerializeObject(tweety)); // {"Name":"Tweety Pie","Type":"Bird","CanFly":true,"Color":"#ffff00"}
    }
}

Another implementation, using it to combine parameters when calling ASP helpers:

    public static object CombineObjects(this object item, object add)
    {
        var ret = new ExpandoObject() as IDictionary<string, Object>;

        var props = item.GetType().GetProperties();
        foreach (var property in props)
        {
            if (property.CanRead)
            {
                ret[property.Name]= property.GetValue(item);
            }
        }

        props = add.GetType().GetProperties();
        foreach (var property in props)
        {
            if (property.CanRead)
            {
                ret[property.Name] = property.GetValue(add);
            }
        }

        return ret;
    }

If you have a class with an object property, or if your property actually casts to an object, you can reshape the object by reassigning its properties, as in:

  MyClass varClass = new MyClass();
  varClass.propObjectProperty = new { Id = 1, Description = "test" };

  //if you need to treat the class as an object
  var varObjectProperty = ((dynamic)varClass).propObjectProperty;
  ((dynamic)varClass).propObjectProperty = new { Id = varObjectProperty.Id, Description = varObjectProperty.Description, NewDynamicProperty = "new dynamic property description" };

  //if your property is an object, instead
  var varObjectProperty = varClass.propObjectProperty;
  varClass.propObjectProperty = new { Id = ((dynamic)varObjectProperty).Id, Description = ((dynamic)varObjectProperty).Description, NewDynamicProperty = "new dynamic property description" };

With this approach, you basically rewrite the object property adding or removing properties as if you were first creating the object with the

new { ... }

syntax.

In your particular case, you're probably better off creating an actual object to which you assign properties like "dob" and "address" as if it were a person, and at the end of the process, transfer the properties to the actual "Person" object.

Related