c# - 参数类型不匹配 Transforming anonymous Expression<Func<T,U>> to non anonymous Expression<Func<T,U>>

标签 c# linq lambda expression visitor-pattern

假设我们有三个这样的类:

public class ParentType {
    private ParentType() {}

    public int Id { get; protected set; }
    public SubType Sub { get; protected set; }
}

public class SubType{
    private SubType(){}

    public int Id { get; protected set; }
    public ICollection<ColSubType> ColSubs{get; protected set;}
}

public class ColSubType{
    private ColSubType(){}

    public int Id { get; protected set; }
    public SubType SubType { get; set; }
}

我有一个这样的匿名表达式:

x => new
{
   x.Id,
   Sub = new
   {
      x.Sub.Id,
      ColSubs = x.Sub.ColSubs.Select(u=> new {
             u.Id
      }).ToList()
   }
}

我需要将其转换为非匿名表达式,如下所示:

x => new ParentType()
{
   Id = x.Id,
   Sub = new SubType()
   {
      Id = x.Sub.Id,
      ColSubs = x.Sub.ColSubs.Select(u=> new ColSubs(){
             Id = u.Id
      }).ToList()
   }
}

感谢@IvanStoev 对这个问题的回答:Variable 'x.Sub' of type 'SubType' referenced from scope '' but it is not defined error我能够转换简单的表达式,但是当我添加 x.Sub.ColSubs.Select(...) 时,出现以下错误:

System.ArgumentException: Argument types do not match

最佳答案

以下是您需要添加到递归 Transform 的代码准确处理该场景的方法,即检测 Select方法,转换 selector参数,修改 TResult Select 的通用类型参数并用新的 selector 调用它, 最后调用 ToList如果目的地不是 IEnumerable<T> :

if (source.Type != type && source is MethodCallExpression call && call.Method.IsStatic
    && call.Method.DeclaringType == typeof(Enumerable) && call.Method.Name == nameof(Enumerable.Select))
{
    var sourceEnumerable = call.Arguments[0];
    var sourceSelector = (LambdaExpression)call.Arguments[1];
    var sourceElementType = sourceSelector.Parameters[0].Type;
    var targetElementType = type.GetGenericArguments()[0];
    var targetSelector = Expression.Lambda(
        Transform(sourceSelector.Body, targetElementType),
        sourceSelector.Parameters);
    var targetMethod = call.Method.GetGenericMethodDefinition()
        .MakeGenericMethod(sourceElementType, targetElementType);
    var result = Expression.Call(targetMethod, sourceEnumerable, targetSelector);
    if (type.IsAssignableFrom(result.Type)) return result;
    return Expression.Call(
        typeof(Enumerable), nameof(Enumerable.ToList), new[] { targetElementType },
        result);
}

关于c# - 参数类型不匹配 Transforming anonymous Expression<Func<T,U>> to non anonymous Expression<Func<T,U>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55809842/

相关文章:

C# ??空合并运算符 LINQ

linq - 我如何使用 Linq 查询计数。查询中的记录

java - Log4j 2 lambda "lazy logging"

c# - 如何使用 Vlc.DotNet 在 Windows Forms c# 中流式传输 RTSP 摄像头源

c# - 抽象可重用库中的合成根

c# - 从多个源接收音频数据并将它们合并到波形文件中

c# - 将展平表的 Linq 投影到父子对象图中

java - 使用时异常? : operator in Java 8 lambda expression

java - 在 Java 8 中测试 Lambda

c# - 从 TableLayoutPanel 中访问组合框的 SelectedIndex