Is there a faster way to cast Fun<TEntity, TId> to Func<TEntity, object>
public static class StaticAccessors<TEntity>
{
public static Func<TEntity, TId> TypedGetPropertyFn<TId>(PropertyInfo pi)
{
var mi = pi.GetGetMethod();
return (Func<TEntity, TId>)Delegate.CreateDelegate(typeof(Func<TEntity, TId>), mi);
}
public static Func<TEntity, object> ValueUnTypedGetPropertyTypeFn(PropertyInfo pi)
{
var mi = typeof(StaticAccessors<TEntity>).GetMethod("TypedGetPropertyFn");
var genericMi = mi.MakeGenericMethod(pi.PropertyType);
var typedGetPropertyFn = (Delegate)genericMi.Invoke(null, new[] { pi });
//slow: lambda includes a reflection call
return x => typedGetPropertyFn.Method.Invoke(x, new object[] { }); //can we replace this?
}
}
Is there a way to convert typedGetPropertyFn to a Func<TEntity, object> without having reflection code in the returned lambda like the example above?
EDIT: added modified solution
Ok thanks to 280Z28 for leading me down the right path which I’ve included in the final solution below. I’ve left the reflection code in there for platforms that don’t support Expressions. For platforms that do it’s showing a 26x to 27x (13 / .5 ticks avg) perf increase for getting int and string properties.
public static Func<TEntity, object> ValueUnTypedGetPropertyTypeFn(PropertyInfo pi)
{
var mi = typeof(StaticAccessors<TEntity>).GetMethod("TypedGetPropertyFn");
var genericMi = mi.MakeGenericMethod(pi.PropertyType);
var typedGetPropertyFn = (Delegate)genericMi.Invoke(null, new[] { pi });
#if NO_EXPRESSIONS
return x => typedGetPropertyFn.Method.Invoke(x, new object[] { });
#else
var typedMi = typedGetPropertyFn.Method;
var obj = Expression.Parameter(typeof(object), "oFunc");
var expr = Expression.Lambda<Func<TEntity, object>> (
Expression.Convert(
Expression.Call(
Expression.Convert(obj, typedMi.DeclaringType),
typedMi
),
typeof(object)
),
obj
);
return expr.Compile();
#endif
}
As you know, you can obtain a
MethodInfofromPropertyInfo.GetGetMethod(). From that, you can use the following to get aFunc<object, object>to retrieve that property. By a similar method, you could return a strongly-typedFunc<TObject, TResult>. For any givenMethodInfo, you should cache the results of this call if you need it more than once since this method is at least an order of magnitude more expensive than calling the resulting delegate.