Вложенная лямбда для использования с интерфейсом Fluent - PullRequest
2 голосов
/ 12 сентября 2009

Даны следующие типы:

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

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

И с учетом следующих методов на помощнике ...

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;
}

Я могу сделать это:

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

Список строк «Свойства» в myHelper будет содержать значение «Дети», то есть имя свойства, переданное через выражение.

То, что я хочу сейчас сделать, - это добиться того же, только с помощью способности отражать иерархию типов.

Будет ли это выглядеть так?

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

Или это вообще возможно, и в чем дело? Я уже видел вложенные лямбды, но не знаю, что с ними связано.

Заранее спасибо!

EDIT

Кажется, есть некоторая путаница, поэтому я попытаюсь уточнить. Я хочу иметь возможность создать строку, которая выглядит как этот «Object.SubObject.SubSubObject», используя лямбда-выражения и цепочки методов. Мой пример делает это, но только для одного уровня (свойство класса). То, что я хочу сделать, это расширить это, чтобы перейти на любую глубину.

Например, я хотел бы использовать лямбда-выражения с плавным интерфейсом, который бы выглядел примерно так ...

AddProps (x => x.Children) .AddProps (xx => xx.GrandChildren) и это добавит «Children.GrandChildren» в мой список строк «Свойства».

Ответы [ 2 ]

2 голосов
/ 12 сентября 2009

Это может упростить ситуацию, если метод AddProps является универсальным, а не весь класс помощника.

Таким образом, вы могли бы иметь этот код:

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

Возможно, вы захотите сохранить больше, чем просто имя свойства, чтобы вы знали, к какому типу принадлежит свойство. Я полагаю, у вас может быть словарь для хранения свойств для каждого зарегистрированного вами типа.

P.S. Знание того, почему вы хотите это сделать, может помочь сообществу SO лучше ответить на ваш вопрос.

0 голосов
/ 13 сентября 2009

Я закончил тем, что использовал альтернативное решение, которое работало довольно хорошо. Он использует этот новый класс ...

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;
    }
}

Теперь, когда у меня есть этот новый класс, я могу сделать это ...

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

Переменная «typeHierarchy» теперь имеет значение «Children.GrandChildren».

Это не так элегантно, как я бы надеялся, но это безопасный и простой в использовании тип.

...