views:

284

answers:

2

Hello,

StackOverflow user jolson had a very nice piece of code that exemplifies how one can register menthods without using strings, but expression trees here.

Is it possible to have something similar for properties instead of methods? To pass a property (not the name of the property) and inside the method to obtain the property name?

Something like this:


    RegisterMethod(p => p.Name)

    void RegisterMethod(Expression??? propertyExpression) where T : Property ???
    {
        string propName = propertyExpression.Name;
    }

Thanks.

+5  A: 

You can write something along this:

static void RegisterMethod<TSelf, TProp> (Expression<Func<TSelf, TProp>> expression)
{
    var member_expression = expression.Body as MemberExpression;
    if (member_expression == null)
     return;

    var member = member_expression.Member;
    if (member.MemberType != MemberTypes.Property)
     return;

    var property = member as PropertyInfo;
    var name = property.Name;

    // ...
}
Jb Evain
Why is the TProp needed? I tested and it works, but I realize I need to learn expression trees.
Vasi
@Vasi - the type of lambda must be explicit. You can't, for example, just use `Expression`. The TProp here refers to the "int" etc that desribes the property. You can let the compiler figure it out, though.
Marc Gravell
TProp expresses the return type of the property, and is needed to describe a method that takes something, and returns something else, ie: the Func<TSelf, TProp>.Then the expression tree is built upon this delegate type.
Jb Evain
+5  A: 

I posted a full example of this here (see also the post about "this" underneath it)

Note it deals with the LambdaExpression etc. As an update to the code as posted, you can add a bit more to make it easier to use in some scenarios:

static class MemberUtil<TType>
{
    public static string MemberName<TResult>(Expression<Func<TType, TResult>> member)
    {
        return MemberUtil.MemberName<TType, TResult>(member);
    }
}

Then you can use generic type-inference for the return value:

string test1 = MemberUtil<Foo>.MemberName(x => x.Bar); 
string test2 = MemberUtil<Foo>.MemberName(x => x.Bloop());
Marc Gravell
Hello Marc,Thanks a lot, that was exactly what I was looking for, to ignore somehow the type of the property.
Vasi
@Vasi - generics are "all or nothing" when it comes to the type inference (maybe we'll have "mumble" typing at some point). The above trick lets the compiler infer the property type without having to specify it ourselves ;-p
Marc Gravell