Marek
Marek

Reputation: 33

How to create expression tree returning restricted set of properties, based on convention?

I need to create an expression tree returning Expression<Func<TDataStructure, Double[]>> expression. Tricky part about it, is that TDataStructure is generic what implies, that each passed class contains different set of properties. I need to get properties of type Double? and names starting with specific string, like "output".

Simple example case (concrete class):

Expression<Func<ConcreteDataStructure, Double[]>> expression =
    structure => new Double[] {
         structure.inputProperty1.Value,
         structure.outputProperty1.Value,
         structure.outputProperty2.Value
    };

where: structure.inputProperty1.Value, structure.outputProperty1.Value, structure.outputProperty2.Value are of type Double?

My case:

  1. I do not know how many properties of type Double? are in TDataStructure

  2. I need to get only these of type Double?, starting with "output"

  3. Expression will be used in IQueryable<TDataStructure> Select method for projection of each sequence element into new form.

Upvotes: 3

Views: 75

Answers (2)

Krzysztof
Krzysztof

Reputation: 16150

Try this:

public static Expression<Func<T, Double[]>> BuildExpression<T>()
{
    ParameterExpression param = Expression.Parameter(typeof(T));
    Expression[] array = typeof(T).GetProperties()
        .Where(p => p.Name.StartsWith("input") || p.Name.StartsWith("output"))
        .OrderBy(p => p.Name)
        .Select(p => (Expression)Expression.Property(Expression.Property(param, p), "Value"))
        .ToArray();

    Expression body = Expression.NewArrayInit(typeof(Double), array);

    return Expression.Lambda<Func<T, Double[]>>(body, param);
}

Upvotes: 3

stop-cran
stop-cran

Reputation: 4408

I'd suggest this:

static Expression<Func<T, double[]>> DoublePropertiesSelector<T>()
{
    var data = Expression.Parameter(typeof(T));

    return Expression.Lambda<Func<T, double[]>>(
        Expression.NewArrayInit(typeof(double),
            from property in typeof(T).GetProperties()
            where property.PropertyType == typeof(double?)
            select Expression.Property(Expression.Property(data, property.Name), "Value")),
        data);
}

If you are okay with possible null-refs, in case your double? has no value.

Upvotes: 1

Related Questions