简体   繁体   English

嵌套Lambda表达式

[英]Nested Lambda Expressions

Does anyone have any idea how I call a lambda expression from within a lambda expression? 有谁知道我如何从lambda表达式中调用lambda表达式?

If I have: 如果我有:

public class CourseViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }

    public static Expression<Func<Course, CourseViewModel>> AsViewModel = x =>
        new CourseViewModel
        {
            Id = x.Id,
            Name = x.Name,
        }
}

public class StudentViewModel
{
    public int Id { get; set; }
    public string Name{ get; set; }
    public string PreferredCheese { get; set; }
    public IEnumerable<CourseViewModel> Courses { get; set; }

    public static Expression<Func<Student, StudentViewModel>> AsViewModel = x =>
        new StudentViewModel
        {
            Id = x.Id,
            Name = x.Name,
            PreferredCheese = x.PreferredCheese,
            Courses = ???I'd like to call the CourseViewModel.AsViewModel here
        }
}

In the code above rather than writing the AsViewModel expression within the StudentViewModel as: 在上面的代码中,而不是在StudentViewModel中将AsViewModel表达式编写为:

Courses = new CourseViewModel
{
    Id = x.Id,
    Name = x.Name,
}

I'd like to call CourseViewModel.AsViewModel to allow code re-use and to keep the code converting a Course to a CourseViewModel in the CourseViewModel class. 我想调用CourseViewModel.AsViewModel以允许代码重用,并保持将Course转换为CourseViewModel类中的CourseViewModel的代码。 Is this possible? 这可能吗?

You can just use x.Courses.Select(c => CourseViewModel.AsViewModel(c)) So your whole expression would be: 您可以只使用x.Courses.Select(c => CourseViewModel.AsViewModel(c))因此您的整个表达式将是:

public static Expression<Func<Student, StudentViewModel>> AsViewModel = x =>
        new StudentViewModel
        {
            Id = x.Id,
            Name = x.Name,
            PreferredCheese = x.PreferredCheese,
            Courses = x.Courses.Select(c => CourseViewModel.AsViewModel(c))
        }

If you want to preserve CourseViewModel.AsViewModel as a nested expression (which you probably do if you're using a LINQ query provider), this gets tricky; 如果您想将CourseViewModel.AsViewModel保留为嵌套表达式(如果您使用的是LINQ查询提供程序,则可能会这样做),这会变得很棘手。 you effectively have to build up the AsViewModel expression in StudentViewModel by yourself: 您必须有效地自己在StudentViewModel构建AsViewModel表达式:

using E = System.Linq.Expressions.Expression; // for brevity

// ...

static StudentViewModel()
{
    var s = E.Parameter(typeof(Student), "s");

    //
    // Quick hack to resolve the generic `Enumerable.Select()` extension method
    // with the correct type arguments.
    //
    var selectMethod = (Expression<Func<Student, IEnumerable<CourseViewModel>>>)
                        (_ => _.Courses.Select(c => default(CourseViewModel)));

    var lambda = E.Lambda<Func<Student, StudentViewModel>>(
        E.MemberInit(
            E.New(typeof(StudentViewModel)),
            E.Bind(
                typeof(StudentViewModel).GetProperty("Id"),
                E.Property(s, "Id")),
            E.Bind(
                typeof(StudentViewModel).GetProperty("Name"),
                E.Property(s, "Name")),
            E.Bind(
                typeof(StudentViewModel).GetProperty("PreferredCheese"),
                E.Property(s, "PreferredCheese")), // LOL?
            E.Bind(
                typeof(StudentViewModel).GetProperty("Courses"),
                E.Call(
                    ((MethodCallExpression)selectMethod.Body).Method,
                    E.Property(s, "Courses"),
                    CourseViewModel.AsViewModel))
            ),
        s);

    AsViewModel = lambda;
}

The resulting expression tree is equivalent to: 生成的表达式树等效于:

s => new StudentViewModel {
    Id = s.Id,
    Name = s.Name,
    PreferredCheese = s.PreferredCheese,
    Courses = s.Courses.Select(x => new CourseViewModel { Id = x.Id, Name = x.Name })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM