mardi 8 août 2017

Get a MemberExpression from a Func

I have a method accepting an array of Expression<Func<T, object>> - the idea being that by downcasting the property type to object that I can represent every property access in the same way. The actual use case is to ignore particular properties when mapping classes using reflection.

Intended to be used like so:

someObject.Map(exclude: x => x.Value, y => y.SomeOtherPropertyWeDontCareAbout);

The expressions I am getting have a Body NodeType of Convert - because they are getting downcast to a return type of object when I create them.

However, now I want to use these expressions to access actual properties on a given instance of T. When I try to do this it looks like I need to convert my expression back to a member access expression. However, casting to a MemberAccessExpression returns null.

If I try to just invoke the expression by calling Compile() and then invoking it, I get null. Code below. How do I convert back to a proper property access so that I can use it to access properties on an instance of T?

    class Program
    {
        static void Main(string[] args)
        {
            var obj = new Test
            {
                Value = "HELLO!"
            };
            var getter = new PropertyMapper().GetMemberAccess<Test>( "Value" );
            object result = getter.Compile()( obj ); //this is null and not 'HELLO!!'
        }
    }

    public class Test
    {
        public string Value { get; set; }
    }

    public class PropertyMapper
    {
        public Expression<Func<T, object>> GetMemberAccess<T>(string propertyName)
        {
            var propInfo = typeof(T).GetProperty( propertyName );
            return GetGetterExpression<T>( propInfo );
        }

        private Expression<Func<T, object>> GetGetterExpression<T>(PropertyInfo propInfo)
        {
            var param = Expression.Parameter(typeof(T), "e");
            Expression propExpression = Expression.Property(param, propInfo);

            if (propInfo.PropertyType != typeof(object))
                propExpression = Expression.Convert(propExpression, typeof(object));

            return Expression.Lambda<Func<T, object>>(propExpression, param);
        }
    }





Aucun commentaire:

Enregistrer un commentaire