2016-05-05 29 views
2

我正嘗試做這樣的事情:的LINQ在以利用可變首

 public class Person{string name;string surname;} 
    //... 
    List<Person> listExample; 
    //We add Person object in listExample 
    string variable="name"; 
    listexample.Where(x=>x.(variable)=="John"); 

它是更多鈔票做同樣的事情?如果您需要訪問的屬性,那麼你可以使用GetProperties(BindingFlags bindingAttr)方法而不是GetFields(...)方法

class Person 
{ 
    public Person(string name) 
    { 
     this.name = name; 
    } 

    string name; 
} 

List<Person> people = new List<Person>() 
{ 
    new Person("Jane"), 
    new Person("John") 
}; 

string variableName = "name"; 
string criteria = "John"; 

var selectedPeople = 
    people 
     .Where(person => 
      typeof(Person) 
       .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
       .Where(fieldInfo => String.Equals(fieldInfo.Name, variableName)) 
       .Select(fieldInfo => fieldInfo.GetValue(person) as string) 
       .SingleOrDefault() == criteria 
     ) 
     .ToList(); 

// At this point 'selectedPeople' will contain one 'Person' named "John" 

+1

的可能的複製[如何創建謂詞動態](http://stackoverflow.com/questions/6383825/how-to-create-predicate-dynamically);也[動態創建一個表達式](http://stackoverflow.com/questions/5094489/how-do-i-dynamically-create-an-expressionfuncmyclass-bool-predicate-from-ex);也[動態創建謂語]](http://stackoverflow.com/questions/845059/how-do-i-dynamically-create-an-expressionfuncmyclass-bool-predicate) – ASh

回答

0

如果您需要訪問非公共字段,那麼你可以使用反射。

class Person 
{ 
    public Person(string name) 
    { 
     this.Name = name; 
    } 

    public string Name { get; set; } 
} 

// in a method 
var selectedPeople = 
    people 
     .Where(person => 
      typeof(Person) 
       .GetProperties(BindingFlags.Public | BindingFlags.Instance) 
       .Where(propertyInfo => String.Equals(propertyInfo.Name, variableName)) 
       .Select(propertyInfo => propertyInfo.GetValue(person) as string) 
       .SingleOrDefault() == criteria 
     ) 
     .ToList(); 

你應該看看BindingFlags枚舉,這樣就可以選擇相應的枚舉值。

  • BindingFlags.Static靜態成員
  • BindingFlags.Instance例如會員
  • BindingFlags.Public公衆成員
  • BindingFlags.NonPublic私人/ protected成員
0

最簡單的方法,考慮到類只有兩個可能的字段進行過濾,將是你SE簡單的if-else塊:

string targetProperty = "name"; 
string targetValue = "John"; 
IEnumerable<Person> query = listExample; 

if(targetProperty == "name") query = query.Where(x => x.name == targetValue) 
else if(targetProperty == "surname") query = query.Where(x => x.surname == targetValue) 

var result = query.ToList(); 

如果實際的類中有很多可能的屬性/字段進行過濾,並要避免過多,如果分支,它的時間來使用Expression如提及問題評論如下:

string targetProperty = "name"; 
string targetValue = "John"; 

var param = Expression.Parameter(typeof(Person), "x"); 
var body = Expression.Equal(
       Expression.PropertyOrField(param, targetProperty), 
       Expression.Constant(targetValue)); 
var predicate = Expression.Lambda<Func<Person, bool>>(body, param); 

var result = listExample.Where(predicate.Compile()).ToList(); 

上述代碼應建立謂詞表達式相當於x => x.name == "John"(因爲targetProperty = "name"targetValue = "John"

+0

這是一個例子來ilustrate我的問題。真正的List是一個包含10個頭文件的sql表,但是謝謝! –

0

有一個nuget package爲這讓你寫;

using System.Linq.Dynamic; //Import the Dynamic LINQ library 

//The standard way, which requires compile-time knowledge 
//of the data model 
var result = myQuery 
    .Where(x => x.Field1 == "SomeValue") 
    .Select(x => new { x.Field1, x.Field2 }); 

//The Dynamic LINQ way, which lets you do the same thing 
//without knowing the data model before hand 
var result = myQuery 
    .Where("Field1=\"SomeValue\"") 
    .Select("new (Field1, Field2)"); 
+0

真棒,正是我需要的!謝謝 –