我有一个 Linq 表达式列表 List<Expression>
其中每个表达式类型(表达式将返回的类型)是 Item
或 Item[]
.
我正在尝试编写一些代码,将提到的集合作为输入参数并生成一个 Linq 表达式,该表达式将返回一个项目列表(或数组)(Item[]
)。
这是一个抽象的例子:
public static string[] GetStrings()
{
return new[]
{
"first",
"second",
"third"
};
}
public static string GetString()
{
return "single1";
}
private void SOExample()
{
var expressions = new List<Expression>
{
Expression.Call(GetType().GetMethod("GetString")),
Expression.Call(GetType().GetMethod("GetStrings")),
Expression.Call(GetType().GetMethod("GetString")),
Expression.Call(GetType().GetMethod("GetStrings"))
};
// some magic code here
var combined = SomeMagicHere(expressions);
}
private Expression SomeMagicHere(List<Expression> expressions)
{
foreach (var expression in expressions)
{
if (expression.Type.IsArray)
{
// Use array's elements
}
else
{
// Use expression
}
}
我想要做的是生成一个表达式,该表达式将返回 Item
的列表。 (在我的示例中为字符串)来自提供的列表。
最佳答案
这似乎是一个非常奇怪的场景,在大多数情况下,我希望在这里看到使用原始反射(或者可能是委托(delegate))而不是 Expression
- 这显然不合适。但是:您可以通过将表达式转换为一个 block 来做到这一点,每个 block 调用 Add
或 AddRange
将值附加到列表中。例如:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
static class Program
{
public static string GetString()
{
return "single1";
}
public static string[] GetStrings()
{
return new[]
{
"first",
"second",
"third"
};
}
static void Main()
{
var expressions = new List<Expression>
{
Expression.Call(typeof(Program).GetMethod("GetString")),
Expression.Call(typeof(Program).GetMethod("GetStrings")),
Expression.Call(typeof(Program).GetMethod("GetString")),
Expression.Call(typeof(Program).GetMethod("GetStrings"))
};
// some magic code here
var combined = SomeMagicHere(expressions);
// show it works
var lambda = Expression.Lambda<Func<List<string>>>(combined);
var list = lambda.Compile()();
}
private static Expression SomeMagicHere(List<Expression> expressions)
{
List<Expression> blockContents = new List<Expression>();
var var = Expression.Variable(typeof(List<string>), "list");
blockContents.Add(Expression.Assign(var,
Expression.New(typeof(List<string>))));
foreach (var expression in expressions)
{
if (expression.Type.IsArray)
{
blockContents.Add(Expression.Call(
var, var.Type.GetMethod("AddRange"), expression));
}
else
{
blockContents.Add(Expression.Call(var,
var.Type.GetMethod("Add"), expression));
}
}
blockContents.Add(var); // last statement in a block is the effective
// value of the block
return Expression.Block(new[] {var}, blockContents);
}
}
关于c# - 如何将多个 Linq 表达式的结果组合成一个表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12779971/