FAQ
overflow

Great Answers to
Questions About Everything

QUESTION

I want to create delegates to access properties of different objects without knowing them in advance.

I have the following definitions

public delegate T MyMethod<K, T>(K data);

public static MyMethod<K, T> CreatePropertyGetter<K, T>(PropertyInfo property)
{       
   MethodInfo mi = property.DeclaringType.GetMethod("get_" + property.Name);        
   return (MyMethod<K, T>)Delegate.CreateDelegate(typeof(MyMethod<K, T>), mi);
}

where T can be decimal, string, datetime or int

I have some initializing code that will create MyMethod delegates, based on the reflected properties of my object as follows:

foreach (PropertyInfo property in entityType.GetProperties())
{               
    switch (property.PropertyType.Name)
    {
        case "System.Decimal":
            return CreatePropertyGetter<T, decimal>(property);
        case "System.DateTime":
            return CreatePropertyGetter<T, DateTime>(property);
        case "System.String":
            return CreatePropertyGetter<T, DateTime>(property);
    }
}

Is there a better way to

  1. create property getters?
  2. enumerate through the supported property types hard-coded as strings?

However, performance is an issue, since these delegates will be called frequently (ticking scenario), so any casting will slow it down. While a more elegant solution is desirable, performance is still my main concern

{ asked by anchandra }

ANSWER

As my answer on Stack Overflow states, there is a solution which allows you to create a getter delegate for any type, so the entire switch block can be dropped. Personally, I find that the cleanest solution. The only overhead of this approach is the cast from object to the specific type where necessary. (For a getter this would happen only once on the return value.) I'm guessing if you would benchmark this, the result would be negligible.

When you are certain that the only types required are those specified, or that no new types are expected very often, you could still opt to use your current approach. I would apply a few changes however:

  1. Use PropertyInfo.GetGetMethod() to retrieve your MethodInfo for the getter.
  2. Use the type of PropertyType directly to determine which CreatePropertyGetter to call instead of the name of the type.
  3. Use Func<K, T> instead of MyMethod.
  4. Use a Dictionary holding anonymous functions which create the correct delegate for the specified type of the key. This can replace the switch statement.

The last point is possible as follows:

Dictionary<Type, Func<PropertyInfo, object>> getterCreators =
    new Dictionary<Type, Func<PropertyInfo, object>>
    {
        { typeof(string), p => CreatePropertyGetter<T, string>(p) },
        { typeof(DateTime), p => CreatePropertyGetter<T, DateTime>(p) },
        { typeof(decimal), p => CreatePropertyGetter<T, decimal>(p) }
    };

Ofcourse you still have to cast from object to the desired type.

UPDATE:

As Timwi pointed out in the comments, p => CreatePropertyGetter<T, ...>(p) can be further reduced to: CreatePropertyGetter<T, ...>.

{ answered by Steven Jeuris }
Tweet