Geeks With Blogs

News
Elton Stoneman (@EltonStoneman) IT Consultant, integration specialist, @Microsoft MVP and @Pluralsight author.

[Source: http://geekswithblogs.net/EltonStoneman]

Supposing you’re using a lambda expression as a neat way to access a named property:

                s => s.FirstName

- when what you really want is to access it without using a string for the property name (“FirstName”), for example to specify the source or target property for a mapping exercise.

It’s easy if the expression is a direct property of the parameter type – a member of the “s” in the expression; casting the whole expression as a MemberExpression gives you access to the member as a PropertyInfo. You can encapsulate it in an extension method of LambdaExpression:

    public static PropertyInfo AsPropertyInfo(this LambdaExpression expression)

    {

        PropertyInfo info = null;

        if (expression.Body.NodeType == ExpressionType.MemberAccess)

        {

            info = ((MemberExpression)expression.Body).Member as PropertyInfo;

        }

        return info;

    }

- which lets you access the property like this:

    Expression<Func<FullUser, object>> exp = s => s.FirstName;

    PropertyInfo sourceProperty = exp.AsPropertyInfo();

But if the expression represents a property of a nested type, or a property of  a nested type of a nested type:

                s => s.Address.Line1

      s => s.Address.PostCode.Code

- then it’s different.

What you want in this case is an executable expression which will access the containing object of the property (e.g. get you the Address property of the source object, or the PostCode property of the Address property of the source object). You also want the PropertyInfo of the target property (e.g. Line1 or Code). And you want both the property accessor and the PropertyInfo from the same expression.

This is not too difficult. It doesn’t require a stack of target objects and PropertyInfos as originally feared. Firstly store the PropertyInfo from the nested target in the normal way:

    targetPropertyInfo = targetExpression.AsPropertyInfo();

- this gives us access to Line1 or Code. Then store the expression which retrieves the path to the containing object for the property from the original source - .Address  or .Address.Postcode. In the expression tree, this is the expression which contains the root to the original parameter:

    if (targetExpression.Body.NodeType == ExpressionType.MemberAccess)

    {

        MemberExpression memberExpression = targetExpression.Body as MemberExpression;

        if (memberExpression.Expression.NodeType != ExpressionType.Parameter)

        {

            ParameterExpression parameter = GetParameterExpression(memberExpression.Expression);

            if (parameter != null)

            {

                _targetExpression = Expression.Lambda(memberExpression.Expression, parameter);

            }

        }

    }

The key line is the one which contains Expression.Lambda(). The parent expression is a MemberExpression (e.g. s.Address, or s.Address.PostCode) which itself is not executable. You can’t compile a MemberExpression and execute it on an object to get the member, as the expression needs to know the parameter it executes against.

Expression.Lambda creates a compilable, executable expression against a provided target parameter – which we already have from the “s” of the original expression, and we can find for any level of nesting:

    private ParameterExpression GetParameterExpression(Expression expression)

    {

        while (expression.NodeType == ExpressionType.MemberAccess)

        {

            expression = ((MemberExpression)expression).Expression;

        }

        if (expression.NodeType == ExpressionType.Parameter)

        {

            return (ParameterExpression)expression;

        }

        return null;

    }

So now we have the PropertyInfo for the nested target, and an expression which will give us the nested target, we can set the target property value like this:

    object target; //this is the top-level object

    //...

    realTarget = expression.Compile().DynamicInvoke(target);

    targetPropertyInfo.SetValue(realTarget, value, null);

It’s quite a complex requirement, but the solution is straightforward and the complexity is isolated from the calling code. Note that the example code above only deals with nested properties, not expressions with mixed properties and method calls (e.g. s.Address.GetPostCode().InwardCode), but it’s straightforward to cover those cases too.


Posted on Thursday, November 5, 2009 10:14 PM Code Snippet | Back to top


Comments on this post: Retrieving Nested Properties from Lambda Expressions

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Great post. Very enlightening. Congratulations.
Left by hospedagem de Sites on May 02, 2010 3:35 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Very good post. It really helped me a lot, will be referring a lot of friends about this.I really enjoy reading your blog.The keyword sniping links are awesome.Keep it up.Thanks for sharing with us.Keep posting.
Left by USANA-46 on Jun 14, 2010 6:07 AM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
little bit confusing, coz i'm totally beginner in scripting. anyway, your posting is good, i learn more on it.
Left by breast cancer symptoms on Jun 19, 2010 12:13 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Thanks for sharing with us, great post.
Left by daily rosetta on Jun 19, 2010 12:19 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Is that PHP? recently i start to learn PHP, its little bit hard for me, since im new for them.
Left by juvenile rheumatoid arthritis on Jun 19, 2010 12:22 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
great bro keep it up
Left by charlotte pet sitting on May 14, 2011 12:00 AM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
we will come back to see if you have any follow up topics ;-) London Indian escorts
Left by London Escorts on Jun 05, 2011 12:41 AM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Very good post. It really helped me a lot, will be referring a lot of friends about this.I really enjoy reading your blog.The keyword sniping links are awesome.Keep it up.Thanks for sharing with us.Keep posting.
Left by saga gold on Jul 16, 2011 8:17 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Very good post.I really enjoy reading your blog.The keyword sniping links are awesome. It really helped me a lot, will be referring a lot of friends about this.Keep it up.Thanks for sharing with us.Keep posting.
Left by saga hair on Jul 17, 2011 5:13 AM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Very good post.I really enjoy reading your blog. It really helped me a lot, will be referring a lot of friends about this.The keyword sniping links are awesome.Keep it up.Thanks for sharing with us.Keep posting.
Left by saga remy on Jul 20, 2011 3:22 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
yeah I am quite agree with you, its really very a good post
Thanks for sharing it with us
regards
Left by small business credit cards on Jul 23, 2011 11:44 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
This blog is very good and informative. It is difficult task but your post and experience serve and teach me how to handle and make it more simple and manageable
________________
custom wine label
Left by darrensy on Aug 25, 2011 5:33 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
I am currently searching for ways in which I could enhance my knowledge in this said topic you have posted here. It does help me a lot knowing that you have shared this information here freely. I love the way the people here interact and shared their opinions too. I would love to track your future posts pertaining to the said topic we are able to read. Cursos de ingles en el extranjero

Left by junies on Oct 12, 2011 5:18 AM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
Well done your script on my site! Thank you very much! I would go more often! Many tests done the all perfect! More such interesting posts from you !)))))
Left by serial on Dec 14, 2011 4:35 PM

# re: Retrieving Nested Properties from Lambda Expressions
Requesting Gravatar...
What about nested collections?
Left by Adam Naylor on Jan 24, 2013 1:51 PM

Your comment:
 (will show your gravatar)
 


Copyright © Elton Stoneman | Powered by: GeeksWithBlogs.net | Join free