MistyK
MistyK

Reputation: 6222

Create a list of Expressions

My goal is to pass a list of expression trees without casting or explicitly specifying type. It's important that I need to pass it as Expression because I do some parsing inside. Example:

  var builder = JobRunnerPayloadBuilder<ITestRunner, double>.CreateBuilder();
   for (int i = 0; i < 2; i++)
{
   builder.Add(x => x.Abc());
}

Then I use builder.Calls to get all expression trees.

How can I pass arguments to AddRange function without casting or specifying the type explicitly? Something along these lines:

builder.AddRange(parameters.Select(parameter => (Expression<Func<TestObject, int>>) (x => x.DoSomething(parameter))).ToList()) //it doesn't work without explicit cast

Builder class:

public class JobRunnerPayloadBuilder<TRunner, TResult>
{
    public List<Expression<Func<TRunner, TResult>>> Calls { get; } = new List<Expression<Func<TRunner, TResult>>>();

    public JobRunnerPayloadBuilder<TRunner, TResult> Add(Expression<Func<TRunner, TResult>> call)
    {
        Calls.Add(call);
        return this;
    }

    public JobRunnerPayloadBuilder<TRunner, TResult> AddRange(IEnumerable<Expression<Func<TRunner, TResult>>> calls)
    {
        Calls.AddRange(calls);
        return this;
    }

    public static JobRunnerPayloadBuilder<TRunner, TResult> CreateBuilder()
    {
        return new JobRunnerPayloadBuilder<TRunner, TResult>();
    }
}

EDIT: More precise example:

public class TestObject
    {
        public int DoSomething(string param1)
        {
            return 1;
        }
    }

  var parameters = new List<string>() { "a", "b", "c" }; // generated somewhere earlier.



var expressions = parameters.Select(parameter => (Expression<Func<TestObject, int>>) (x => x.DoSomething(parameter))).ToList();

Compiler needs explicit cast to expression here. Is there a way to workaround it? JobRunnerPayloadBuilder was a "try" to avoid specifying the type explicitly but it does work only for single argument

Upvotes: 0

Views: 1847

Answers (1)

Servy
Servy

Reputation: 203812

You can create a simple static method that will allow you to construct an Expression using a lambda in a context where it knows that the lambda is supposed to be an expression, and allowing it to infer the return return type:

public static Expression<Func<TSource, TResult>> CreateExpression<TSource, TResult>(
    Expression<Func<TSource, TResult>> expression)
{
    return expression;
}

var expressions = parameters.Select(parameter => 
    CreateExpression((TestObject x) => x.DoSomething(parameter))
.ToList();

Upvotes: 1

Related Questions