如何将表达式 Func<T, object[]> 转换为 Func<T, object>?

3

我有一个需要在linq查询中选择的字段数组。
这些字段格式为Expression<Func<T, object[]>>。(字段数组)
(我不能改变这个,其他代码需要保留字段的顺序)

我需要将其转换为可用于IQueryable<T>中的选择器。 但是怎么做呢? 我该如何实现GetSelector()函数?

var fields = GetFields<Employee>(e => new[] { e.Name, e.Street });
var selector = GetSelector(fields);
var result = await qry.Select(selector).ToListAsync();

GetFields函数:

private Expression<Func<T, object[]>> GetFields<T>(Expression<Func<T, object[]>> fields)
{
    return fields;
}

GetSelector函数:

private Expression<Func<T, object>> GetSelector<T>(Expression<Func<T, object[]>> fields)
{
    //How to convert? 
    //It should return somehting like this: (e => new {e.Name, e.Street})
}

据我所知,您无法从委托中获取任何信息(例如访问的参数/成员等),您需要使用表达式树。您无法直接从委托中获取字段的名称(即 e.Namee.Street)。您可以尝试执行委托,然后使用反射分析返回的对象类型(即匿名类型),但这听起来更像是一种解决方法(而且可能容易出错)......因此,我想您要么需要更改 GetFields() 的签名以使用表达式而不是委托,要么找到完全不同的解决方案... - bassfader
抱歉,当您输入评论时,我已经将其更改为表达式。 - roeland
你能详细解释一下你计划中的用法吗?我无法理解你拥有这样一个选择器表达式后想要做什么。 - grek40
@r03 这感觉像是在重新发明轮子。为什么不使用一个表达式来返回一个匿名对象,该对象将封装字段名称和它们的值。 - Nkosi
1个回答

1

我对IQueryable部分不是很确定(请测试一下),但更改表达式签名非常容易,因为object[]是一个object

private static Expression<Func<T, object>> GetSelector<T>(Expression<Func<T, object[]>> fields)
{
    var result = Expression.Lambda<Func<T, object>>(fields.Body, fields.Parameters);
    return result;
}

看起来它能工作...我没想到它会这么简单。我需要更多地了解表达式树。 - roeland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接