Есть ли более быстрый способ отбрасывать Fun<TEntity, TId>
в 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?
}
}
Есть ли способ конвертировать typedGetPropertyFn
в Func<TEntity, object>
без кода отражения в возвращенной лямбда, как в примере выше?
EDIT: добавлено модифицированное решение
Хорошо благодаря 280Z28 для того, чтобы вести меня по правильному пути, который я включил в окончательное решение ниже. Я оставил код отражения там для платформ, которые не поддерживают выражения. Для платформ, которые делают это, демонстрируют увеличение 26x до 27x (13/.5 тиков) для получения свойств int
и string
.
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
}