Search code examples
c#castingactivator

Instantiate class based on json value


Say I have two classes :

public class male 
{
   public string name { get; set; }
   public int age { get; set; }
}

public class female 
{
   public string name { get; set; }
   public int age { get; set; }
}

I have some JSON data like so :

{
    "people" : [
        {
            "name" : "fred",
            "age" : 45,
            "gender" : "male"
        },
        {
            "name" : "jane",
            "age" : 45,
            "gender" : "female"
        }   
    ]
}

I wish to loop through this JSON data and depending on the gender of the person, instantiate the corresponding class.

For example :

JObject data = jsonData.people;

for(var i = 0; i< data.Count; i++) {
   JObject thisPerson = data[i];
   var instantiatePerson = new {thisPerson.gender}; //obviously this will not work
}

Now the above is just an example, hopefully that will explain what I need.

I have tried using the Activator.CreateInstance like so :

var type = Type.GetType("myNamespace" + person.gender);
var myObject = Activator.CreateInstance(type);

This verifies but I can't loop through the object and give the instantiated class the property values like so :

foreach(var key in person) {
   myObject[key] = person[key];
}

I get the error :

Cannot apply indexing with [] to an expression of type object.

Which leads me to think I have to cast myObject to it's appropriate type, but how?


Solution

  • In C#, an object isn't an associative array of its properties. That's JavaScript. If you really need to do things this way, use reflection to set the properties.

    Something like this:

    PropertyInfo[] props = myObject.GetType().GetProperties();
    
    foreach (var propInfo in props)
    {
        if (person.ContainsKey(propInfo.Name))
        {
            propInfo.SetValue(myObject, person[propInfo.Name]);
        }
    }
    

    or

    var type = myObject.GetType();
    
    foreach (var key in person) {
        var prop = type.GetProperty(key);
        if (prop != null)
        {
             prop.SetValue(myObject, person[key]);
        }
    }
    

    But I think a better answer is that you should probably be redesigning your classes instead. male and female could be one Person class with a gender property as well as name and age -- exactly like what's in the JSON.

    Conventional JSON serialization isn't broken. Is there really a compelling need to reinvent it?