0

I want access to a property value by its name. The only way i know it's by reflection with a code like this:

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

Are there others ways to do it (using ex. codegen, etc.)?

Gianluigi Liguori
  • 311
  • 1
  • 5
  • 12
  • 2
    Codegen and building an expression tree which you then compile into a function. – Jon Oct 30 '15 at 20:17
  • 1
    If you need to keep a parameter of type `object` and a result of type `object`, go the codegen way as Jon says. But if you can use strongly typed functions, creating a delegate to the property getter is both smpler to code, and faster at runtime (as it avoids an intermediary step). – Lucas Trzesniewski Oct 30 '15 at 20:23
  • Of course, i'm talking about object types. Can you show me (as answer) some implentation using this method? – Gianluigi Liguori Oct 30 '15 at 21:22

1 Answers1

1

The only way I know it's by reflection with a code like this:

Reflection is one way, it's also expensive (so I've heard), so you create a cache to speed up multiple property looks ups (this is what does). Something like (totally example code):

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;
}

(*maybe you could use a HashSet instead since PropertyInfoKey could technically hold the PropertyInfo as well, and it's implementing IEquatable)

OR....

If you are doing this because you have a lot of classes that share similar properties but are completely different and unrelated...

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; }
}

Then you can

public static string GetName(this IName instance)
{
  return instance.Name;
}
Erik Philips
  • 48,663
  • 7
  • 112
  • 142