2012-01-24 21 views
7

Dado que tengo un IEnumerable<T>, donde T es cualquier objeto, ¿cómo puedo seleccionar una propiedad específica de él, dado que sé el nombre de uno de los nombres de propiedad en tiempo de ejecución como una cadena?¿Cómo puedo crear una selección dinámica en un IEnumerable <T> en tiempo de ejecución?

Por ejemplo:

var externalIEnumerable = DataPassedFromConsumingCode(); // `IEnumerable<T>` 

string knownPropertyName = "Foo"; 
var fooSelect = externalIEnumerable.Select(...); 

En esencia, obviamente estoy simplemente haciendo externalIEnumerable.Select(x=> x.Foo);, pero necesito para realizar este Select en tiempo de ejecución, cuando no tengo control sobre cuando se crea inicialmente.

-

RESPUESTA: Sobre la base de la respuesta de Alant, esto es lo que realmente hice:

public Expression<Func<TItem, object>> SelectExpression<TItem>(string fieldName) 
{ 
    var param = Expression.Parameter(typeof(TItem), "item"); 
    var field = Expression.Property(param, fieldName); 
    return Expression.Lambda<Func<TItem, object>>(field, 
     new ParameterExpression[] { param }); 
} 

que lo mantuvieron como una expresión, porque llamando Compile causó la IQueryable de estar numerado, que significaba que la base de datos fue golpeada innecesariamente. Por lo tanto, para usarlo, simplemente hacer lo siguiente:

string primaryKey = _map.GetPrimaryKeys(typeof(TOriginator)).Single(); 
var primaryKeyExpression = SelectExpression<TOriginator>(primaryKey); 
var primaryKeyResults = query.Select(primaryKeyExpression).ToList(); 
+0

¿se puede restringir T en IEnumerable? – Jason

+1

Esta no es una pregunta específica de linq, ¿verdad? ¿Está preguntando cómo acceder a una propiedad dinámicamente por nombre en lugar de estáticamente en el código? –

+0

Para aclarar, su T podría ser cualquier cosa, su propiedad podría ser cualquier cosa, ¿simplemente tendrá el nombre de la propiedad como una cadena? –

Respuesta

6

Es posible hacer esto utilizando una expresión

por ejemplo,

private class Foo { 
    public string Bar { get; set; } 
} 

private IEnumerable<Foo> SomeFoos = new List<Foo>() { 
    new Foo{Bar = "Jan"}, 
    new Foo{Bar = "Feb"}, 
    new Foo{Bar = "Mar"}, 
    new Foo{Bar = "Apr"}, 
}; 

[TestMethod] 
public void GetDynamicProperty() { 

     var expr = SelectExpression<Foo, string>("Bar"); 
     var propValues = SomeFoos.Select(expr); 

     Assert.IsTrue(new[] { "Jan", "Feb", "Mar", "Apr" }.SequenceEqual(propValues)); 

    } 

public static Func<TItem, TField> SelectExpression<TItem, TField>(string fieldName) { 

    var param = Expression.Parameter(typeof(TItem), "item"); 
    var field = Expression.Property(param, fieldName); 
    return Expression.Lambda<Func<TItem, TField>>(field, new ParameterExpression[] { param }).Compile(); 

} 

HTH,
Alan.

0

Usted puede construir dinámicamente una Expression<Func<T, U>>.

Cuestiones relacionadas