2016-07-28 26 views
3

Ich muss einen Ausdrucksbaum erstellen, der Expression<Func<TDataStructure, Double[]>> expression zurückgibt. Das heikelste daran ist, dass TDataStructure generisch ist, was impliziert, dass jede übergebene Klasse unterschiedliche Eigenschaften enthält. Ich brauche Eigenschaften des Typs Double? und Namen beginnend mit bestimmten Zeichenfolge, wie "output".Wie erstellt man einen Ausdrucksbaum, der basierend auf der Konvention einen eingeschränkten Satz von Eigenschaften zurückgibt?

Einfaches Beispiel Fall (Betonklasse):

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

wo: structure.inputProperty1.Value, structure.outputProperty1.Value, structure.outputProperty2.Value vom Typ sind Doppel?

Mein Fall:

  1. Ich weiß nicht, wie viele Eigenschaften des Typs Double? sind in TDataStructure

  2. muss ich nur diese vom Typ Double?, erhalten mit "output" Start

  3. Ausdruck wird in IQueryable<TDataStructure> Select Methode für die Projektion von jedem Sequenzelement in neue Form verwendet werden.

+0

Beide 1 und 2 können mit Reflexion gelöst werden: Blick auf 'Type.GetProperties()' oder 'TypeInfo.GetProperties()' (je nachdem, welche Reflection-API Sie verwenden). –

+0

Das weiß ich. Aber ich weiß nicht, wie ich es in Expression verwenden soll. var properties = typeof (Trainieren Data die Trainieren) .GetProperties() .Where (property => property.PropertyType == typeof (Doppel) && property.Name.ToLowerInvariant() Starts ("Produkt")?!.); – Marek

+0

@Marek: Richtig, also, sobald Sie die Eigenschaften gefunden haben, die Sie verwenden möchten, können Sie 'Expression.Property' verwenden, um einen Ausdruck für jede dieser Eigenschaften zu erstellen ... –

Antwort

3

Versuchen Sie folgendes:

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

Das löste es! – Marek

1

Ich würde dies vorschlagen:

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

Wenn Sie in Ordnung sind mit möglichem Null-Refs, falls Ihre double? keinen Wert haben.