0

I am trying to get class property name and its data type dynamically for any class so that I can build schema model required for Db e.g. Google BigQuery. I was able to get the string or int property name and Type but with array or list of custom class am not sure how to get their class property and name.

My model is :

public class StateModel
{
    public string State { get; set; }
    public string Gender { get; set; }
    public int Year { get; set; }
    public string Name { get; set; }
    public int Number { get; set; }

    public int[] Items { get; set; }
    public List<string> Values { get; set; }

    public Coordinate[] OrdinateArray { get; set; }
    public List<Coordinate> Ordinates { get; set; }

    public Coordinate CoordinateObj { get; set; }
}

public class Coordinate
{
    public int Point { get; set; }
    public string Value { get; set; }
}

My method to get class property is:

public static Dictionary<string, object> GetColumnFromClass<T>() where T : class, new()
{
    Dictionary<string, object> fields = new Dictionary<string, object>();
    T obj = new T();
    var type = obj.GetType();    
    PropertyInfo[] properties = type.GetProperties();
    foreach (var item in properties)
    {
        fields.Add(item.Name, item.PropertyType.Name.ToUpper())
    }
    return fields;
}

Can anyone help me how to get Coordinate class details i.e.(Point and Value name of Coordinate class) from the below properties:

public Coordinate[] OrdinateArray { get; set; }
public List<Coordinate> Ordinates { get; set; }
public Coordinate CoordinateObj { get; set; }

Note: I needed to get the subclass details dynamically and not hard coded.

imsome1
  • 1,182
  • 4
  • 22
  • 37
Joshua I
  • 550
  • 3
  • 8
  • 22
  • @DiskJunky my question is not to determine only if its collection but to get the collection property name and its data type as well. I have clearly mentioned in my question – Joshua I Oct 03 '17 at 12:01
  • like this: https://stackoverflow.com/questions/5949688/how-to-iterate-the-list-in-reflection? – DiskJunky Oct 03 '17 at 12:03
  • @DiskJunky sorry am not iterating any list. This class is just a generic type and I need to get all its property name and datatype and nothing to do with property value. I apprecitae your effort trying to help but my question is simple how to get the custom subclass property name and its data type if that class is decared as simple class, List<> or[]. – Joshua I Oct 03 '17 at 12:08
  • Apologies, I didn't get that from the question. To clarify, are you trying to get the type `Coordinate` from the property `OrdinateArray`? It looks like you already have the property name, you're just missing the type...if I'm understanding you correctly? – DiskJunky Oct 03 '17 at 12:11
  • @DiskJunky bingo thats right. Since the type is custom class I may also require to read all the property name and datatype of custom class as well.. – Joshua I Oct 03 '17 at 12:47
  • Then is the following not appropriate: https://stackoverflow.com/a/557349/1838819? – DiskJunky Oct 03 '17 at 12:57

1 Answers1

1

Please see if this will meet your requirement (Same property name in parent and child will lead to only one entry of parent, this can be handled with a recursion depth parameter):

private static ConcurrentDictionary<string, object> GetColumnFromClass(object obj, ConcurrentDictionary<string, object> fields)
        {
            //null type will not be processed
            if (obj == null)
                return null;

            Type objType = obj.GetType();
            PropertyInfo[] properties = objType.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                {
                    Type itemType = property.PropertyType.GetGenericArguments()[0];
                    if (itemType == typeof(string))
                        fields.AddOrUpdate(property.Name, property.PropertyType.Name.ToUpper(), (k, o) => o);
                    else
                    {
                        fields.AddOrUpdate(property.Name, property.PropertyType.Name.ToUpper(), (k, o) => o);
                        GetColumnFromClass(Activator.CreateInstance(itemType), fields);
                    }
                }
                else
                {
                    object propVal = property.GetValue(obj, null);
                    if (property.PropertyType.Assembly == objType.Assembly)
                    {
                        fields.AddOrUpdate(property.Name, property.PropertyType.Name.ToUpper(), (k,o) => o);
                        GetColumnFromClass(propVal, fields);
                    }
                    else
                    {
                        fields.AddOrUpdate(property.Name, property.PropertyType.Name.ToUpper(), (k, o) => o);
                    }
                }
            }
            return fields;
        }
Dhejo
  • 71
  • 5