Using expression trees to get property getter and setters

There are times when you need get and set property values and you do not know the type of the properties. One option is use reflection through GetValue and SetValue from PropertyInfo class, but this wears to poor performance in our code.

In order to do that we can use an Expression Tree to generate delegates that allow to get and set the value of the required property, for example building a couple of extensions methods applying to PropertyInfo:

 

public static class PropertyInfoExtensions

{

    public static Func<T, object> GetValueGetter<T>(this PropertyInfo propertyInfo)

    {

        if (typeof(T) != propertyInfo.DeclaringType)

        {

            throw new ArgumentException();

        }

 

        var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");

        var property = Expression.Property(instance, propertyInfo);

        var convert = Expression.TypeAs(property, typeof(object));

        return (Func<T, object>)Expression.Lambda(convert, instance).Compile();

    }

 

    public static Action<T, object> GetValueSetter<T>(this PropertyInfo propertyInfo)

    {

        if (typeof(T) != propertyInfo.DeclaringType)

        {

            throw new ArgumentException();

        }

 

        var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");

        var argument = Expression.Parameter(typeof(object), "a");

        var setterCall = Expression.Call(

            instance,

            propertyInfo.GetSetMethod(),

            Expression.Convert(argument, propertyInfo.PropertyType));

        return (Action<T, object>)Expression.Lambda(setterCall, instance, argument)

                                            .Compile();

    }

}

 

Now, we can use this extensions methods to retrieve the delegates for get or set a value, assuming that we have a class called ReflectedType and we have a valid PropertyInfo for this class:

 

var getter = property.GetValueGetter<ReflectedType>();

var setter = property.GetValueSetter<ReflectedType>();

 

Finally we can get or set the value, assuming that we have a valid instance of the ReflectedType type:

 

setter(reflectedType, 0);

var value = getter(reflectedType));

 

You can get the code here.

No Comments