1

I have an expression that has the following structure. I get it from a Expression.ArrayIndex, so I cannot change it:

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

Afterwards I'm combining this expression with a parent one that has this structure:

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

So the resultant expression should be:

Expression<Func<TDataSource, TProperty>>

Note that after combining them I use TDataSource as input and i get TProperty as result. However I cannot combine them because TModel[] cannot be cast to IEnumerable<TModel>.

The combine is done like this:

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);
    }
}

*More info about ExpressionRewriter: https://stackoverflow.com/a/1720642/1587864

I want to keep using IEnumerable, and I really need an Array in the other expression. Is there any way I can do a casting of those expressions somehow, before merging them?

Thank you

Community
  • 1
  • 1
margabit
  • 2,924
  • 18
  • 24

2 Answers2

1

You can use LINQ's Enumerable.ToArray as an intermediate expression.

Expression<Func<IEnumerable<TModel>, TModel[]>> toArray = x => x.ToArray();
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
1

Assuming you had:

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

Why can't you just do:

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

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

You can try to be a little cuter with the converter if possible:

Expression<Func<IEnumerable<TModel>, TModel[]>> converter 
              = seq => (seq as TModel[]) ?? seq.ToArray();
Ani
  • 111,048
  • 26
  • 262
  • 307