2011-03-30 26 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);