2011-03-30 61 views
1

場我有這樣的對象:使用變量值與LINQ

public class MyObject 
{ 
    public int Id { get; set; } 
    public string FieldA { get; set; } 
    public string FieldB { get; set; } 
    public string FieldC { get; set; } 
    public string FieldD { get; set; } 
} 

我有一個IList <此對象>:

IList<MyObject> MyListObject = new List<MyObject>(); 

我做的LINQ查詢就可以了:

var result = (from p in MyListObject where p.FieldC == "Test" select p.FieldA); 

在這種情況下,我返回「p.FieldA」,但有時我需要返回「p.FieldB」。我希望把字段(FIELDA或FieldB)的名稱在一個變量這樣

var myvar = "FieldB" 
var result = (from p in MyListObject where p.FieldC == "Test" select p.????); 

如何在LINQ查詢使用MYVAR內容(FieldB)的字段名?

謝謝,

回答

5

如果你的方法本身知道它FIELDA和FieldB之間作出選擇,你可以使用:

var whatField = "FieldA"; 
var result = (from p in MyListObject 
    where p.FieldA == "Test" 
    select (whatField == FieldA ? p.FieldA : p.FieldB)); 

如果您有更多的作爲2個選項,我會選擇傳遞一個lambda;

Func<MyObject, object> fieldGetter; 

// Option A, switch 
switch (whatField) { 
    case "FieldA": fieldGetter = o => o.FieldA; break; 
    case "FieldB": fieldGetter = o => o.FieldB; break; 
    // More options 
} 

// Option B using reflection: 
var t = typeof(MyObject); 
var prop = t.GetProperty(whatField); 
fieldGetter = o => prop.GetValue(o, null); 

// Linq then looks like 
var result = (from p in MyListObject 
    where p.FieldA == "Test" 
    select fieldGetter(p)); 

使用lambda的好處是,你可以拆分你的邏輯,什麼字段和如何查詢。而且您甚至可以使其適用於不同類型:

IEnumerable<T> Query<T>(IQueryable<MyObject> MyListObject, Func<MyObject, T> fieldGetter) { 
    return result = (from p in MyListObject 
     where p.FieldA == "Test" 
     select fieldGetter(p)); 
} 

// call using: 

var result = Query(MyListObject, o => o.FieldA); 
+0

這將無法正常工作,因爲你的fieldGetter是Func ,這將工作只有當你的fieldGetter類型爲Expression >時,你會得到一個運行時不支持Invoke的錯誤。你將不得不結合linq表達式。 – 2011-03-30 08:23:41

+0

選項2是一個很好的答案,因爲它允許您通過向交換機添加更多條目來添加更多的字段選擇。 – SecretDeveloper 2011-03-30 08:27:05

+0

@Akash Kava,對於LINQ to Objects,它會起作用。反射在數據庫服務器上無效,所以我認爲不使用表達式語法更安全。如我錯了請糾正我。 – GvS 2011-03-30 08:32:21

0

FieldA和FieldB是相同類型嗎?

如果是的話,那麼你可以做這樣的事情:

var result = (from p in MyListObject where p.FieldA == "Test" 
      select (condition ? p.FieldA : p.FieldB)); 
+0

同類型是。你的解決方案是可以的,對於2場,但我的班級可以有3場。我想要另一種解決方案,而不是開關 – 2011-03-30 08:11:05

+0

但是,您希望如何選擇適當的字段?必須有一些邏輯。你當然可以選擇一種方法,但仍然在這種方法會有如果或切換(或任何其他解決方案來選擇良好的領域) – 2011-03-30 08:26:18

0

您可以使用反射來根據其名稱獲取屬性的值。這將允許您選擇課程中的任何屬性。

下面是一個使用擴展方法上的MyObject類的例子:然後

public static string GetPropertyValue(this MyObject myObj, string propertyName) 
    { 
     var propInfo = typeof(MyObject).GetProperty(propertyName); 

     if (propInfo != null) 
     { 
      return propInfo.GetValue(myObj, null).ToString(); 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 

你的LINQ查詢應該是這樣的:

string propName = "FieldB"; 
var result = from m in myList where m.FieldC == "Test" select m.GetPropertyValue(propName); 
0

如果你想讓它與IQueryable的工作,你可以做這樣的事情:

var filtered = MyListObject.Where(p => p.FieldA == "Test"); 

var results = condition ? filtered.Select(p => p.FieldA) : filtered.Select(p => p.FieldB); 

它可以被重構爲:

Expression<Func<MyObject,string>> selector; 

switch(condition) 
{ 
    case "FieldA": selector = o => o.FieldA; break; 
    case "FieldB": selector = o => o.FieldB; break; 
    // other cases here 
    default: throw new NotImplmentedException(); 
} 

var results = MyListObject.Where(p => p.FieldA == "Test").Select(selector);