-1

I am looking to use CsvHelper dynamically by building up Expressions in code which represent property member access for a given type.

The method I am trying to pass these expressions to has the following signature:

    public virtual CsvPropertyMap<TClass, TProperty> Map<TProperty>( Expression<Func<TClass, TProperty>> expression )
    {
        //
    }

So you would normally call it, for any given type you want to map, like this (for a type with a property called 'stringProperty'):

mapper.Map(x => x.StringProperty);

Passing in a lambda which is converted internally into an Expression<Func<T, object>>

I have tried to create this expression in code, using Expressions. At compile time it all works fine (in that it returns an Expression<Func<TModel, object>>), but at runtime I get an exception 'not a member access'. Here is the code which takes a PropertyInfo object representing the property I want to map:

    private Expression<Func<TModel, object>> CreateGetterExpression( PropertyInfo propertyInfo )
    {
        var getter = propertyInfo.GetGetMethod();

        Expression<Func<TModel, object>> expression = m => getter.Invoke( m, new object[] { } );
        return expression;
    }

Basically, how do I build that Expression up properly in code?

thisextendsthat
  • 1,099
  • 7
  • 23
  • 2
    Is the property type actually `object`? Also, if you have a `PropertyInfo` object already, why not just call `PropertyInfo.GetValue()` instead of trying to invoke the getter method? Also, what's the point of using reflection here? Without a good [mcve] it's hard to see what you're really trying to achieve and what specific difficulty you're having. – Peter Duniho Jul 12 '17 at 21:26
  • I share Peter's concerns, but hope this similar question and answer here: https://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet can help you. – Eugène Jul 12 '17 at 21:28

1 Answers1

5

Just try something looks like this:

    public static Expression<Func<T, P>> GetGetter<T, P>(string propName)
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = Expression.Property(parameter, propName);
        return Expression.Lambda<Func<T, P>>(property, parameter);
    }

    public static Expression<Func<T, P>> GetGetter<T, P>(PropertyInfo propInfo)
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = Expression.Property(parameter, propInfo);
        return Expression.Lambda<Func<T, P>>(property, parameter);
    }

It's example of usages:

    private class TestCalss
    {
        public int Id { get; set; }
    }

    private static void Main(string[] args)
    {
        var getter = GetGetter<TestCalss, int>(typeof(TestCalss).GetProperty("Id")).Compile();
        Console.WriteLine(getter(new TestCalss { Id = 16 }));
    }
George Alexandria
  • 2,643
  • 2
  • 14
  • 24