通过字符串名称访问类的属性的有效方法

时间:2015-10-30 20:08:55

标签: c# reflection codegen

我希望通过名称访问属性值。我知道它的唯一方法就是用这样的代码反思:

 public static object GetPropValue(object src, string propName)
 {
     return src.GetType().GetProperty(propName).GetValue(src, null);
 }

还有其他方法吗(使用ex.codegen等)?

1 个答案:

答案 0 :(得分:1)

  

我知道它的唯一方法就是用这样的代码反射:

反射是一种方式,它也很昂贵(所以我听说过),所以你创建了一个缓存来加速多个属性查找(这就是所做的)。像(完全是示例代码)的东西:

private static Dictionary<PropertyInfoKey, PropertyInfo> propertyCache = 
  new Dictionary<PropertyInfoKey, PropertyInfo>()

private class PropertyInfoKey : IEquatable 
{
  public PropertyInfoKey(string fullName, string propertyName)
  {  
    FullName = fullName;
    PropertyName = propertyName
  }

  public string FullName { get; private set; }
  public string PropertyName { get; private set; }

  public bool Equals(PropertyInfoKey other)
  {
    if ( ..// do argument checking

    var result = FullName == other.FullName
      && PropertyName == other.PropertyName;

    return result;
  }
}

public static bool TryGetPropValue<T>(T src, 
  string propName, 
  out object value)
  where T : class
{
  var key = new PropertyInfoKey(
    fullName: typeof(T).FullName,
    propertyName: propName
  );

  PropertyInfo propertyInfo;
  value = null;
  var result = propertyCache.TryGetValue(key, out propertyInfo);

  if (!result)
  {
    propertyInfo = typeof(T).GetProperty(propName);

    result = (propertyInfo != null);

    if (result)
    {
      propertyCache.Add(key, propertyInfo)
    }  
  }

  if (result)
  {
    value = propertyInfo.GetValue(src, null);
  }
  return result;
}

(*也许您可以使用HashSet,因为PropertyInfoKey在技术上也可以保留PropertyInfo,并且它正在实施IEquatable

  

... OR

如果你这样做是因为你有很多类共享类似属性但是完全不同且不相关的类......

public interface IName
{
  public string Name { get; }
}

public class Car : IName
{
  public string Name { get; set; }
  public string Manufacturer { get; set; }
}

public class Animal : IName
{
  public string Name { get; set; }
  public string Species { get; set; }
}

public class Planet : IName
{
  public string Name { get; set; }
  public string ContainSystem { get; set; }
}

然后你可以

public static string GetName(this IName instance)
{
  return instance.Name;
}