2014-12-24 63 views
0

通常當我想,例如找到一個列表的第一或默認的項目我用這樣的方式:是否可以動態設置條件的屬性?

myList.SingleOrDefault(x=>x.MyPropery01 == "myCondition"); 

不過,我想知道這是否是可能的,例如通過反射,如果我設置該物業MyProperty動態,是這樣的:

myList.SingleOrDefault(x=>x.GetType().GetProperty("MyProperty01") == "myCondition"); 

因爲有時候我需要尋找MyProperty01,有時MyProperty02MyProperty03等。

編輯:在Visual Studio中我得到這個錯誤:

"Operator '==' can't be applied to operands of type System.reflection.PropertyInfo and string". 
+1

是的,那是有效的。你是否嘗試過並遇到問題? – BradleyDotNET

+3

不確定它會按原樣工作,但似乎應該在理論上起作用。你試過了嗎?順便說一句,第一個樣本獲取_only_結果或默認值(如果有多個匹配,它會拋出異常,不返回第一個)。 –

+1

你能通過一個表達嗎?無論如何,代碼似乎是有效的,可能工作 –

回答

2

是的,你可以做到這一點。你非常接近,這裏是一個你可以在linqpad中放置的演示。需要注意的是重要的部分是

Single(l => l.GetType().GetProperty(prop).GetValue(l).ToString() == "Condition")

void Main() 
{ 
var myList = Enumerable.Range(0,10).Select(i => new Xmas(i,"name"+i)).ToList(); 
string prop = "name"; 
Console.WriteLine(myList.Single(l => l.GetType().GetProperty(prop).GetValue(l).ToString() == "name6").name); 
} 

public class Xmas 
{ 
public int id { get; set; } 
public string name { get; set; } 
public Xmas(int id, string name) 
{ 
    this.id = id; 
    this.name = name; 
} 
} 
+0

沒有人向您展示您必須使用propertyInfo方法SetValue來設置它。 –

+1

@john:這個問題有什麼用? –

+2

@JohnPeters - 爲什麼有人會在這裏使用SetValue?這是關於在枚舉時獲取值的。列表的值已經在第一行實例化了。 –

1

工作例如:

public class Apple 
{ 
    public string Color { get; set; } 
} 

public List<Apple> ApplesList {get;set;} 

public void Process() 
{ 
    PropertyInfo pi = typeof(Apple).GetProperty("Color"); 
    ApplesList = ApplesList.Where(r => (string)pi.GetValue(r) == "Red").ToList(); 
} 
1

你也可以寫一個擴展方法,允許讓每一個對象的屬性,當它不存在返回null,或者沒有一個GetMethod。你可以保持一個高速緩存,如果你想

public static class ObjectExtension 
{ 
    static IDictionary<KeyValuePair<Type, string>, PropertyInfo> propertyCache = new Dictionary<KeyValuePair<Type, string>, PropertyInfo>(); 

    public static object GetProperty(this object source, string propertyName, bool useCache = true) 
    { 
     if (source == null) 
     { 
      return null; 
     } 
     var sourceType = source.GetType(); 
     KeyValuePair<Type, string> kvp = new KeyValuePair<Type, string>(sourceType, propertyName); 
     PropertyInfo property = null; 

     if (!useCache || !propertyCache.ContainsKey(kvp)) 
     { 
      property = sourceType.GetProperty(propertyName); 
      if (property == null) 
      { 
       return null; 
      } 
      var get = property.GetGetMethod(); 
      if (get == null) 
      { 
       return null; 
      } 
      if (useCache) 
      { 
       propertyCache.Add(kvp, property); 
      } 
     } 
     else 
     { 
      property = propertyCache[kvp]; 
     } 
     return property.GetValue(source, null); 
    } 

    public static T GetProperty<T>(this object source, string propertyName) 
    { 
     object value = GetProperty((object)source, propertyName); 
     if (value == null) 
     { 
      return default(T); 
     } 
     return (T)value; 
    } 
} 

一個小的測試類可以接着是:

public class Item 
{ 
    public string MyProperty { get; set; } 

    public string MyProperty3 { get; set; } 

    public string MyProperty2 { protected get; set; } 

    public Item() 
    { 
     MyProperty = "Test propery"; 
     MyProperty3 = "Test property 3"; 
     MyProperty2 = "Yoohoo"; 
    } 
} 

隨着測試

class Program 
{ 
    static void Main(string[] args) 
    { 
     Item item = new Item(); 
     for (int x = 0; x < 4; x++) 
     { 
      string key = "MyProperty" + (x > 0 ? x.ToString() : ""); 
      string value = item.GetProperty<string>(key); 
      Console.WriteLine("Getting {0} = {1}", key, value); 
     } 
     Console.ReadLine(); 
    } 
} 

它給出了可預期的輸出端的主類:

Getting MyProperty = Test propery 
Getting MyProperty1 = 
Getting MyProperty2 = 
Getting MyProperty3 = Test property 3 
相關問題