2014-12-24 130 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 
相关问题