views:

341

answers:

2

Given the following types:

class Parent { List<Child> Children {get;set;}}
class Child {List<Child> GrandChildren {get;set;}}

class Helper<TEntity> {List<string> Properties {get;set;}}

And given the following methods on Helper...

public Helper AddProps<TEntity, TProp>(Expression<Func<TEntity, TProp>> exp)
{
     this.Properties.Add(GetPropInfo(exp).Name);
}

public PropertyInfo GetPropInfo(Expression<Func<TEntity, TProp>> exp)
{
     return (PropertyInfo)((MemberExpression)(expression.Body)).Member;
}

I am able to do this:

Helper<Parent> myHelper = new Helper<Parent>();
myHelper.AddProps(x => x.Children);

The string list "Properties" on myHelper would then contain the value "Children", the name of the property passed through the expression.

What I want to do now is to be able to achieve the same thing, only with the ability to reflect type hierarchy.

Would it look like this ?

x => x.Children { xx => xx.GrandChildren }

Or is it even possible, and what would be involved? I've seen nested lambda's before but don't know what's involved.

Thanks in advance!

EDIT

It seems there is some confusion so I'll try to clarify. I want to be able to create a string that looks like this "Object.SubObject.SubSubObject" using lambda expressions and method chaining. My example does this, but only for one level deep ( a property of a class). What I want to do is extend this to go to any depth.

For Example, I'd like to use lambda expressions with a fluent interface that would look something like this....

AddProps(x => x.Children).AddProps(xx => xx.GrandChildren) and that would add "Children.GrandChildren" to my "Properties" string list.

+1  A: 

It might make things easier if the AddProps method is generic, instead of the entire Helper Class.

In this way you could have this code:

var helper = new Helper();
helper.AddProps<Parent>(x => x.Children);
helper.AddProps<Child>(x => x.GrandChildren);

You might also want to retain more than just the property name so that you know which type the property belongs to. I guess you could have a Dictionary to store the properties for each type you've registered.

P.S. Knowing why you want to do this might help the SO community better answer your question.

Jeremy Wiebe
A: 

I ended up using an alternate solution that worked quite well. It uses this new class...

public class PartBuilder
{
    private List<string> Parts;

    /// <summary>
    /// Gets a dot delimited string representing the parts
    /// </summary>
    public string Value
    {
        get
        {
            return string.Join(".", this.Parts.ToArray());
        }
    }

    /// <summary>
    /// Creates a new PartBuilder
    /// </summary>
    private PartBuilder()
    {
        this.Parts = new List<string>();
    }


    /// <summary>
    /// Creates a new PartBuilder
    /// </summary>
    public static PartBuilder Create()
    {
        return new PartBuilder();
    }


    /// <summary>
    /// Gets a property name from an expression
    /// </summary>
    public PartBuilder AddPart<TEntity, TProp>(Expression<Func<TEntity, TProp>> expression)
    {
        PropertyInfo prop = (PropertyInfo)((MemberExpression)(expression.Body)).Member;
        this.Parts.Add(prop.Name);

        return this;
    }
}

Now that I have this new class, I can do this...

string typeHierarchy = PartBuilder.Create()
                         .AddPart((Parent p) => p.Children)
                         .AddPart((Child pp) => pp.GrandChildren)
                         .Value;

The variable "typeHierarchy" now has the value of "Children.GrandChildren".

It's not as elegant as I would have hoped, but it's type safe and easy to use.

Matthew