LINQ - 将 MemberBinding 表达式追加到现有的 MemberInit 表达式中

LINQ - append MemberBinding expression into exist MemberInit expression

基本思路类似于Merging Expression Trees to Reuse in Linq Queries

在我的情况下,我有两个模型和 DTO:

public class User
{
  public int Id { get; set; }
  public string Name { get; set; }
  public Extra Extra { get; set; }
}
public class Extra
{
  public int Id { get; set; }
  public string Text { get; set; }
}
public class UserDto
{
  public int Id { get; set; }
  public string Name { get; set; }
  public ExtraDto Extra { get; set; }
}
public class ExtraDto
{
  public int Id { get; set; }
  public string Text { get; set; }
}

和表达式:

Expression<Func<Extra, ExtraDto>> extraSelector = o => new ExtraDto
{
  Id = o.Id,
  Text = o.Text
};
Expression<Func<User, UserDto>> userSelector = o => new UserDto
{
  Id = o.Id,
  Name = o.Name
};

现在,我想'append'extraSelector变成userSelector。伪代码如下:

var selectorExpression = userSelector.Append(user => user.Extra, extraSelector);
Context.Users.Select(selectorExpression).ToList();

最终的表达式是这样的:

Expression<Func<User, UserDto>> userSelector = o => new UserDto
{
  Id = o.Id,
  Name = o.Name,
  Extra = new ExtraDto
  {
    Id = o.Extra.Id,
    Text = o.Extra.Text
  }
};

我试过使用 ExpressionVisitor,但没有成功。

除了两个选择器的"merge"外,你还必须将"path"o => o.Extra插入extraSelector并为"bind expression"创建一个新的"bind expression" UserDto 的 属性 Extra

事实上,我在 this project 中尝试过这样的场景,我试图在其中抽象出这种表达式管道。你的 "merge" 看起来像这样:

userSelector = extraSelector.Translate()
                            .Cross<User>(o => o.Extra)
                            .Apply(o => o.Extra, userSelector);

Translate扩展方法只是利用类型推断的一个小帮手,Crosso => o.Extra插入extraSelectorApply创建"bind expression" 用于 UserDto 的 属性 Extra 最后将结果与 userSelector.

合并