Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get both fields and properties in single call via reflection?

Tags:

c#

reflection

I apologize if this is covered somewhere. I did research before posting!

okay, so question...I'm using GetType( ).GetProperties, but it isn't returning simple instance fields, which don't have get/set on them...so I used .GetFields, which finds them, but I want to get a simple single object to get/set a value on without flipping between fields and properties...is this possible?

my current code works on PropertyInfo, which is working great, but that isn't for fields I guess?

[edit] this is the solution I came up with, which is working good. thanks everyone....

    // some logic borrowed from James Newton-King, http://www.newtonsoft.com
    public static void SetValue(this MemberInfo member, object property, object value)
    {
        if (member.MemberType == MemberTypes.Property)
            ((PropertyInfo)member).SetValue(property, value, null);
        else if (member.MemberType == MemberTypes.Field)
            ((FieldInfo)member).SetValue(property, value);
        else
            throw new Exception("Property must be of type FieldInfo or PropertyInfo");
    }

    public static object GetValue(this MemberInfo member, object property)
    {
        if (member.MemberType == MemberTypes.Property)
            return ((PropertyInfo)member).GetValue(property, null);
        else if (member.MemberType == MemberTypes.Field)
            return ((FieldInfo)member).GetValue(property);
        else
            throw new Exception("Property must be of type FieldInfo or PropertyInfo");
    }

    public static Type GetType(this MemberInfo member)
    {
        switch (member.MemberType)
        {
            case MemberTypes.Field:
                return ((FieldInfo)member).FieldType;
            case MemberTypes.Property:
                return ((PropertyInfo)member).PropertyType;
            case MemberTypes.Event:
                return ((EventInfo)member).EventHandlerType;
            default:
                throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
        }
    }
like image 541
Timmerz Avatar asked Oct 01 '12 20:10

Timmerz


2 Answers

How about:

const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
MemberInfo[] members = type.GetFields(bindingFlags).Cast<MemberInfo>()
    .Concat(type.GetProperties(bindingFlags)).ToArray();

Alternatively, libraries like FastMember will work happily with either fields or properties, with get/set identical regardless of the member-type.

like image 181
Marc Gravell Avatar answered Oct 13 '22 00:10

Marc Gravell


The return types of GetProperties() and GetFields() are different, as you seem to have noticed. You would have to define an interface with the GetValue() and SetValue() and use extend ParameterInfo and FieldInfo to implement this interface. This would probably work as a wrapper:

interface IGetSettable
{
    public void SetValue(
        Object obj,
        Object value,
        Object[] index);
    public Object GetValue(
        Object obj,
        Object[] index);
}

public class ParameterInfoGS : IGetSettable
{
    protected ParameterInfo pi;

    public ParameterInfoExtra(ParameterInfo _pi)
    {
        pi = _pi;
    }

    public void SetValue(
        Object obj,
        Object value,
        Object[] index) {pi.SetValue(obj, value, index);}
    public Object GetValue(
        Object obj,
        Object[] index) {return pi.GetValue(obj, index);}
}

public class FieldInfoGS : IGetSettable
{
    protected FieldInfo pi;

    public FieldInfoExtra(FieldInfo _pi)
    {
        pi = _pi;
    }

    public void SetValue(
        Object obj,
        Object value,
        Object[] index) {pi.SetValue(obj, value, index);}
    public Object GetValue(
        Object obj,
        Object[] index) {return pi.GetValue(obj, index);}
}

public static class AssemblyExtension
{
    public static IGetSettable[] GetParametersAndFields(this Type t)
    {
        List<IGetSettable> retList = new List<IGetSettable>();

        foreach(ParameterInfo pi in t.GetParameters())
            retList.Add(new ParameterInfoExtra(pi));

        foreach(FieldInfo fi in t.GetFields())
            retList.Add(new FieldInfoExtra(fi));

        return retList.ToArray();
    }
}

This will allow you to do GetType().GetParametersAndFields() (i.e. use the standard reflection types).

like image 11
CrazyCasta Avatar answered Oct 13 '22 01:10

CrazyCasta