rukiman
rukiman

Reputation: 643

Getting property and field values from an object using reflection and using a string to specify the field name

OK So I'm using the code below which I found in stack overflow.

    // so we can use reflection to access the object properties
    public static Object GetPropValue(this Object obj, String name)
    {
        foreach (String part in name.Split('.'))
        {
            if (obj == null) { return null; }

            Type type = obj.GetType();
            PropertyInfo info = type.GetProperty(part);
            if (info == null) { return null; }

            obj = info.GetValue(obj, null);
        }
        return obj;
    }

    // so we can use reflection to access the object properties
    public static T GetPropValue<T>(this Object obj, String name)
    {
        Object retval = GetPropValue(obj, name);
        if (retval == null) { return default(T); }

        // throws InvalidCastException if types are incompatible
        return (T)retval;
    }

To get access to a object property using a string. So I can do stuff like this:

DateTime.Now.GetPropValue<int>("TimeOfDay.Hours")

which works well.

But my class doesn't use properties and I cannot change it as it is part of a library. I believe the it is using fields instead of properties (I didn't know they were treated differently in C# till now!). How do I access these field names and properties together? i.e for a class like this

class Student
{
   public string name {get; set;}  // property
   public int age; // field
   public Info info; // field
}

class Info
{
   string a {get; set;} // property
   string b; // fields
}

So I can access using this:

Student a;
a.GetPropValue<string>("info.a");  // getting a property which works!
a.GetPropValue<string>("info.b");  // getting a field value which doesn't!

As soon as I posted this I figured it out and here is my modified function

    // so we can use reflection to access the object properties
    public static Object GetPropertyOrFieldValue(this Object obj, String name)
    {
        foreach (String part in name.Split('.'))
        {
            if (obj == null) { return null; }

            Type type = obj.GetType();
            PropertyInfo propertyInfo = type.GetProperty(part);
            FieldInfo fieldInfo = type.GetField(part);
            if (propertyInfo == null && fieldInfo == null) 
            { 
                return null; 
            }

            obj = (propertyInfo != null) ? propertyInfo.GetValue(obj, null) : (fieldInfo != null) ? fieldInfo.GetValue(obj) : null;
        }
        return obj;
    }

    // so we can use reflection to access the object properties
    public static T GetPropertyOrFieldValue<T>(this Object obj, String name)
    {
        Object retval = GetPropertyOrFieldValue(obj, name);
        if (retval == null) { return default(T); }

        // throws InvalidCastException if types are incompatible
        return (T)retval;
    }

Upvotes: 1

Views: 1677

Answers (1)

DavidG
DavidG

Reputation: 118977

Here is the equivalent code to get a field instead of a property:

public Object GetFieldValue(this Object obj, String name)
{
    foreach (String part in name.Split('.'))
    {
        if (obj == null) { return null; }

        Type type = obj.GetType();
        FieldInfo info = type.GetField(part);
        if (info == null) { return null; }

        obj = info.GetValue(obj);
    }
    return obj;
}

// so we can use reflection to access the object properties
public T GetFieldValue<T>(this Object obj, String name)
{
    Object retval = GetFieldValue(obj, name);
    if (retval == null) { return default(T); }

    // throws InvalidCastException if types are incompatible
    return (T)retval;
}

Upvotes: 1

Related Questions