How do I build this c# "Expression" at runtime using reflection?
Asked Answered
O

2

10

To this day, I have not found a great article about expressions - and how to look at a C# lambda statement and say "oh, that's a blah blah"... so, if you know of a good article, I'd appreciate that as an answer too.

Code sample to explain the question

So... given the following c# code:

public class SomeClass<T>
{
    public TResult SomeMethod<TResult>(Expression<Func<T, TResult>> expression)
    {
        // This is just an example... don't get hung up on this :)
        return default(TResult);
    }
}

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

How do I do this...

var blah = new SomeClass<Person>();

blah.SomeMethod(p => p.FirstName);

at runtime (using reflection)?

What I expect as an answer

I kinda expect something like this... but I'm sure I'm way off with my choice of expressions.

// By the way, these values are being passed to me... so you
// can't change this part of the question :)
Type personType = typeof(Person);
string propertyName = "FirstName";

// THIS CODE BELOW IS OBVIOUSLY WRONG, BUT YOU GET THE IDEA OF
// WHAT I HOPE TO DO... THIS LINE OF CODE BELOW IS **ALL** I'M
// ASKING HOW TO DO :)
var expression = Expression.MakeUnary(ExpressionType.Lambda,
    Expression.Property(Expression.Parameter(personType, "p"),
    propertyName), typeof(string));

blah.SomeMethod(expression);
Ossification answered 16/12, 2011 at 20:0 Comment(0)
T
6

Try this:

var functorParam = Expression.Parameter(typeof(Person));
var lambda = Expression.Lambda(
    Expression.Property(functorParam, typeof(Person).GetProperty("FirstName"))
,   functorParam /* <<= EDIT #1 */
);
blah.SomeMethod((Expression<Func<Person,string>>)lambda); /* EDIT #2 */
Tedious answered 16/12, 2011 at 20:7 Comment(4)
blah.SomeMethod(f); does not compile... but I feel that this is very close.Ossification
@TimothyKhouri If I understand your intent correctly, SomeMethod should be taking Func<T,TResult> functor rather than Expression<Func<T,TResult>> expression. This way you'd be able to write things like var personsProp = functor(myPerson); and get the last name.Tedious
The method that I'm calling into cannot change... it's part of an assembly I'm referencing, and therefor don't have the option to change it... that's why I'm asking this question :)Ossification
@TimothyKhouri Remove lambda.Compile and pass the lambda then.Tedious
S
1

ExpressionBuilder is the way to go.

Spectacled answered 16/12, 2011 at 20:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.