在表达式树Func中将IEnumerable转换为Array

时间:2013-04-03 15:12:42

标签: c# .net-3.5 lambda expression-trees func

我有一个具有以下结构的表达式。我是从Expression.ArrayIndex得到的,所以我无法改变它:

Expression<Func<TModel[], TProperty>> expression

之后我将这个表达式与具有这种结构的父表达式结合起来:

Expression<Func<TDataSource, IEnumerable<TModel>>> dataSourceExpression

因此结果表达式应为:

Expression<Func<TDataSource, TProperty>>

请注意,在合并后我使用TDataSource作为输入,我得到TProperty作为结果。 但是我无法合并它们,因为TModel[]无法转换为IEnumerable<TModel>

联合收割机是这样完成的:

Expression<Func<TDataSource, TProperty>> outputWithoutInline = dataSourceExpression.Combine(expression, true);

public static class ExpressionUtils
{
    public static Expression<Func<T1, T3>> Combine<T1, T2, T3>(
        this Expression<Func<T1, T2>> outer, Expression<Func<T2, T3>> inner, bool inline)
    {
        var invoke = Expression.Invoke(inner, outer.Body);
        Expression body = inline ? new ExpressionRewriter().AutoInline(invoke) : invoke;
        return Expression.Lambda<Func<T1, T3>>(body, outer.Parameters);
    }
}

*有关ExpressionRewriter的更多信息:https://stackoverflow.com/a/1720642/1587864

我想继续使用IEnumerable,我真的需要在另一个表达式中使用Array。在合并它们之前,有什么方法可以以某种方式对这些表达式进行转换吗?

谢谢

2 个答案:

答案 0 :(得分:1)

您可以使用LINQ的Enumerable.ToArray作为中间表达式。

Expression<Func<IEnumerable<TModel>, TModel[]>> toArray = x => x.ToArray();

答案 1 :(得分:1)

假设你有:

Expression<Func<TDataSource, IEnumerable<TModel>>> first = ...
Expression<Func<TModel[], TProperty>> second = ...

为什么你不能这样做:

Expression<Func<IEnumerable<TModel>, TModel[]>> converter = seq => seq.ToArray();

var result = first.Combine(converter, true).Combine(second, true);

如果可能的话,您可以尝试使用转换器:

Expression<Func<IEnumerable<TModel>, TModel[]>> converter 
              = seq => (seq as TModel[]) ?? seq.ToArray();