T,T2>更快的施放Func键<途径;到Func键< T,对象> ;? [英] Faster way to cast a Func<T, T2> to Func<T, object>?
问题描述
有投娱乐与下一个更快的方法; TEntity,TID>
到 Func键< TEntity,对象>
公共静态类StaticAccessors< TEntity>
{
公共静态Func键< TEntity,TID> TypedGetPropertyFn<&TID GT;(的PropertyInfo PI)
{
VAR MI = pi.GetGetMethod();
回报率(Func键< TEntity,TID>)Delegate.CreateDelegate(typeof运算(Func键< TEntity,TID>),MI);
}
公共静态Func键< TEntity,对象> ValueUnTypedGetPropertyTypeFn(的PropertyInfo PI)
{
VAR MI = typeof运算(StaticAccessors< TEntity>)实现getMethod(TypedGetPropertyFn);
VAR genericMi = mi.MakeGenericMethod(pi.PropertyType);
VAR typedGetPropertyFn =(代表)genericMi.Invoke(空,新的[] {PI});
//慢:拉姆达包括反射调用
返回X => typedGetPropertyFn.Method.Invoke(X,新的对象[] {}); //我们可以更换吗?
}
}
有没有一种方法来转换 typedGetPropertyFn
到 Func键< TEntity,对象>
,而不必像上面的例子中,返回的lambda反射代码
编辑:添加修改的方案
块引用>
好感谢280Z28领导我下来我已经包含在下面的最终解决方案的正确道路。我已经离开了反射代码在那里不表示支持的平台。对于平台,做它呈现出的 26倍为 27倍(13 / 0.5蜱平均)PERF的获取增加
INT
和字符串
属性公共静态Func键< TEntity,对象> ValueUnTypedGetPropertyTypeFn(的PropertyInfo PI)
{
VAR MI = typeof运算(StaticAccessors< TEntity>)实现getMethod(TypedGetPropertyFn);
VAR genericMi = mi.MakeGenericMethod(pi.PropertyType);
VAR typedGetPropertyFn =(代表)genericMi.Invoke(空,新的[] {PI});
#如果NO_EXPRESSIONS
返回X => typedGetPropertyFn.Method.Invoke(X,新的对象[] {});
的#else
VAR typedMi = typedGetPropertyFn.Method;
VAR OBJ = Expression.Parameter(typeof运算(对象),oFunc);
VAR EXPR = Expression.Lambda<&Func键LT; TEntity,对象>> (
Expression.Convert(
Expression.Call(
Expression.Convert(OBJ,typedMi.DeclaringType),
typedMi
)
的typeof(对象)
)
OBJ
);
返回expr.Compile();
#ENDIF
}
解决方案如你所知,你可以得到一个
的MethodInfo
从PropertyInfo.GetGetMethod()
。从这一点,你可以用下面的获得<为code> Func键<对象,对象> 来检索该属性。通过类似的方法,你可以返回一个强类型的Func键< TObject的,TResult>
。对于任何给定的MethodInfo
,您应该缓存这个调用的结果,如果你需要比一次更因为这种方法至少是一个数量级比调用产生的代表更贵私有静态Func键<对象,对象> BuildAccessor(MethodInfo的方法)
{
ParameterExpression OBJ = Expression.Parameter(typeof运算(对象),目标文件);
表达式来; Func键<对象,对象>> EXPR =
Expression.Lambda<&Func键LT;对象,对象>>(
Expression.Convert(
Expression.Call(
Expression.Convert(OBJ,method.DeclaringType)
法),
的typeof(对象)),
OBJ);
返回expr.Compile();
}
Is there a faster way to cast
Fun<TEntity, TId>
toFunc<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 aFunc<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
andstring
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
MethodInfo
fromPropertyInfo.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.private static Func<object, object> BuildAccessor(MethodInfo method) { ParameterExpression obj = Expression.Parameter(typeof(object), "obj"); Expression<Func<object, object>> expr = Expression.Lambda<Func<object, object>>( Expression.Convert( Expression.Call( Expression.Convert(obj, method.DeclaringType), method), typeof(object)), obj); return expr.Compile(); }
这篇关于T,T2>更快的施放Func键<途径;到Func键< T,对象> ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!