c# - 使用表达式构建器进行选择的动态 lambda

标签 c# linq lambda

我正在尝试编写动态选择语句。我有以下内容:

public class MainList
{
    public string Prop1{ get; set; }
    public string Prop2{ get; set; }
    public string Prop3{ get; set; }       
}

public class SearchObject
{
    public string Prop1{ get; set; }
}

我想构建如下表达式

var newList = MainList.Select(n => new SearchObject { Prop1 = n.Prop1});

我使用的代码创建了一个基于 MainList 的列表。然后,我暂时通过传递 SearchObject 类型和我想要填充的参数来创建选择表达式。它一直运行到倒数第二行。

public void Start()
{
    List<MainList> newList = new List<MainList>(); //This has a ton list objects
    var result = newList.Select(CreateSelect<SearchObject>("Prop1"));
}

public static Func<MainList, T> CreateSelect<T>(string fields)
{
    var par = Expression.Parameter(typeof(T), "n");

    var newInstance= Expression.New(typeof(T));

    var bindings = fields.Split(',').Select(o => o.Trim())
        .Select(n => {

            var p = typeof(T).GetProperty(n);

            var original = Expression.Property(par, p);

            return Expression.Bind(p, original);
        }
    );

    var newT= Expression.MemberInit(newInstance, bindings);

    var lambda = Expression.Lambda<Func<MainList, T>>(newT, par); //ERROR HAPPENS HERE
    return lambda.Compile();
}

我得到的错误是:

附加信息:“WebApplication.SearchObject”类型的参数表达式不能用于“WebApplication.MainList”类型的委托(delegate)参数

我不确定错误的含义以及如何解决问题。

最佳答案

第一个问题是,正如 Jeroen van Langen 已经提到的,参数的类型必须是 MainList

第二个问题是Expression.Bind的用法.由于源和目标是不同的类型,您不能使用同一个 PropertyInfo。第一个参数必须是目标类型 TPropertyInfo,而第二个 - 表达式来自源类型 MainList(在您的情况下, Expression.Property 在具有指定属性名称的参数上)。

正确的实现是这样的:

public static Func<MainList, T> CreateSelect<T>(string fields)
{
    var parameter = Expression.Parameter(typeof(MainList), "n");
    var bindings = fields.Split(',')
        .Select(name => name.Trim())
        .Select(name => Expression.Bind(
            typeof(T).GetProperty(name),
            Expression.Property(parameter, name)
        ));
    var newT = Expression.MemberInit(Expression.New(typeof(T)), bindings);
    var lambda = Expression.Lambda<Func<MainList, T>>(newT, parameter);
    return lambda.Compile();
}

关于c# - 使用表达式构建器进行选择的动态 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42559581/

相关文章:

c# - Linq C# 基于变量的查询

java - 方法签名包括抛出异常?

c++ - 为什么我可以在 lambda 中使用 ostream cout,尽管它没有被捕获?

c# - 将 int 转换为 boolean 值的更好方法

c# - 如何用外部文本文件填充文本框并在此之后向其中添加单词

c# - 在 UWP 中播放流中的音频

node.js - 如何在 AWS RDS 上配置 MySQL 文档存储

c# - 在这种情况下如何使用 outputcache?

c# - 使用 LINQ 合并对象列表

c# - AutoMapper继承和Linq