用于 Fluent Interface 的嵌套 Lambda

发布于 2024-08-04 08:51:44 字数 1388 浏览 2 评论 0原文

给定以下类型:

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

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

并给定 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;
}

我能够做到这一点:

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

字符串列表“Properties”然后 myHelper 将包含值“Children”,即通过表达式传递的属性的名称。

我现在想做的是能够实现同样的事情,只是具有反映类型层次结构的能力。

它看起来像这样吗?

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

或者它是否可能,以及会涉及什么?我以前见过嵌套 lambda,但不知道涉及什么。

提前致谢!

编辑

似乎有些混乱,所以我会尽力澄清。我希望能够使用 lambda 表达式和方法链接创建一个类似于“Object.SubObject.SubSubObject”的字符串。我的示例执行了此操作,但仅适用于一层深度(类的属性)。我想做的是将其扩展到任何深度。

例如,我想使用带有流畅接口的 lambda 表达式,看起来像这样...

AddProps(x => x.Children).AddProps(xx => xx.GrandChildren) ,这会添加“Children.GrandChildren”到我的“属性”字符串列表。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绳情 2024-08-11 08:51:44

如果 AddProps 方法是通用的,而不是整个 Helper 类,那么事情可能会变得更容易。

通过这种方式,您可以得到以下代码:

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

您可能还希望保留的不仅仅是属性名称,以便您知道该属性属于哪种类型。我想您可以有一个字典来存储您注册的每种类型的属性。

PS 知道你为什么要这样做可能会帮助 SO 社区更好地回答你的问题。

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.

北城半夏 2024-08-11 08:51:44

我最终使用了一个效果很好的替代解决方案。它使用这个新类...

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”。

它并不像我希望的那样优雅,但它类型安全并且易于使用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文