2012-01-24 24 views
7

鑑於我有一個IEnumerable<T>,其中T是任何對象,我怎麼能從它中選擇一個特定的屬性,因爲我知道在運行時的一個屬性名稱的名稱作爲一個字符串?如何在運行時在IEnumerable <T>上創建動態選擇?

例如:

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

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

從本質上說,我明明只是做externalIEnumerable.Select(x=> x.Foo);,但我需要執行此Select在運行時,當我沒有當它最初創建了控制。

-

答:基於AlanT的答案,這是我實際做:

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

我一直是作爲一種表達,因爲調用Compile造成的IQueryable被枚舉,其意味着數據庫被不必要地擊中。因此,要使用它,我只是做到以下幾點:

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

你可以在IEnumerable中約束T嗎? – Jason

+1

這不是一個特定於linq的問題,對吧?你問的是如何通過名稱而不是靜態地在代碼中動態訪問屬性? –

+0

爲了澄清,你的T可以是任何東西,你的財產可以是任何東西,你只需要將屬性名稱作爲一個字符串? –

回答

6

這是可能做到這一點使用表達式

例如

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

} 

心連心,
艾倫。

0

您可以動態建立一個Expression<Func<T, U>>

相關問題