2012-01-24 12 views
7

Dato che ho uno IEnumerable<T>, dove T è un qualsiasi oggetto, come posso selezionare una proprietà specifica da esso, dato che conosco il nome di uno dei nomi di proprietà in fase di esecuzione come una stringa?Come posso creare una selezione dinamica su un oggetto IEnumerable <T> in fase di runtime?

Ad esempio:

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

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

In sostanza, Sono ovviamente solo facendo externalIEnumerable.Select(x=> x.Foo);, ma ho bisogno di eseguire questa Select in fase di esecuzione, quando non ho il controllo su quando viene inizialmente creato.

-

RISPOSTA: Sulla base di risposta di Alant, ecco cosa ho effettivamente fatto:

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

ho tenuto come espressione, perché chiamando Compile causato l'IQueryable per essere enumerati, che significava che il database veniva colpito inutilmente. Quindi, per utilizzarlo, ho solo effettuare le seguenti operazioni:

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

è possibile limitare T in IEnumerable? – Jason

+1

Questa non è una domanda specifica per linq, giusto? Stai chiedendo come accedere a una proprietà dinamicamente per nome anziché staticamente nel codice? –

+0

Per chiarire, il tuo T potrebbe essere qualsiasi cosa, la tua proprietà potrebbe essere qualsiasi cosa, avrai semplicemente il nome della proprietà come una stringa? –

risposta

6

E 'possibile farlo utilizzando un'espressione

esempio

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

È possibile costruire dinamicamente un Expression<Func<T, U>>.

Problemi correlati