从编译表达式返回值类型
Returning value type from compiled expression
我有一些非常动态的代码,这些代码最初使用 Type.GetProperty
和 PropertyInfo.GetValue
的反射来从对象中获取值。然后我读了这篇关于 GetValue
:
的表现
https://lotsacode.wordpress.com/2010/04/12/getting-data-through-reflection-getvalue/
并决定像在 post 中那样通过创建和缓存委托来尝试改进。所以我创建了这样的东西:
private Delegate MakeAccessDelegate(PropertyInfo p)
{
var delType = typeof(Func<,>);
var genType = delType.MakeGenericType(p.DeclaringType, p.PropertyType);
var mi = p.GetAccessors().First();
return Delegate.CreateDelegate(genType, mi);
}
但是,因为我不知道委托的类型,所以我不得不使用 DynamicInvoke
,从好的方面来说,这并不比 GetValue
更糟,但是好像也好点了。
所以我搜索了一下,发现了这个问题和答案:
alternative for using slow DynamicInvoke on muticast delegate
接受的答案建议使用编译委托,这听起来很有帮助。由于我的方法只是属性 getters,我需要稍微改变一下并想出这个(我对表达式树一无所知,所以我在这里有点盲目):
delegate object CachedMethodDelegate(object instance);
private CachedMethodDelegate MakeAccessDelegate(PropertyInfo p)
{
var methodInfo = p.GetAccessors().First();
var instance = Expression.Parameter(typeof(object), "instance");
var lambda = Expression.Lambda<CachedMethodDelegate>(
Expression.Call(
Expression.Convert(instance, methodInfo.DeclaringType),
methodInfo
),
instance
);
return lambda.Compile();
}
这似乎有效。除了一个小皱纹。如果 属性 是值类型(例如 double
或 datetime
),则它无法创建 lambda。它在行 var lambda = ...
上抛出一个 ArgumentException
错误:
Expression of type 'System.Nullable`1[System.Double]' cannot be used
for return type 'System.Object'
显然它无法处理值类型的自动装箱和拆箱。有没有办法让这个工作?
对 Expression.Call
的结果调用 Expression.Convert
并将其转换为 object
。这样就会在需要对类型进行装箱的情况下进行装箱操作。
我有一些非常动态的代码,这些代码最初使用 Type.GetProperty
和 PropertyInfo.GetValue
的反射来从对象中获取值。然后我读了这篇关于 GetValue
:
https://lotsacode.wordpress.com/2010/04/12/getting-data-through-reflection-getvalue/
并决定像在 post 中那样通过创建和缓存委托来尝试改进。所以我创建了这样的东西:
private Delegate MakeAccessDelegate(PropertyInfo p)
{
var delType = typeof(Func<,>);
var genType = delType.MakeGenericType(p.DeclaringType, p.PropertyType);
var mi = p.GetAccessors().First();
return Delegate.CreateDelegate(genType, mi);
}
但是,因为我不知道委托的类型,所以我不得不使用 DynamicInvoke
,从好的方面来说,这并不比 GetValue
更糟,但是好像也好点了。
所以我搜索了一下,发现了这个问题和答案:
alternative for using slow DynamicInvoke on muticast delegate
接受的答案建议使用编译委托,这听起来很有帮助。由于我的方法只是属性 getters,我需要稍微改变一下并想出这个(我对表达式树一无所知,所以我在这里有点盲目):
delegate object CachedMethodDelegate(object instance);
private CachedMethodDelegate MakeAccessDelegate(PropertyInfo p)
{
var methodInfo = p.GetAccessors().First();
var instance = Expression.Parameter(typeof(object), "instance");
var lambda = Expression.Lambda<CachedMethodDelegate>(
Expression.Call(
Expression.Convert(instance, methodInfo.DeclaringType),
methodInfo
),
instance
);
return lambda.Compile();
}
这似乎有效。除了一个小皱纹。如果 属性 是值类型(例如 double
或 datetime
),则它无法创建 lambda。它在行 var lambda = ...
上抛出一个 ArgumentException
错误:
Expression of type 'System.Nullable`1[System.Double]' cannot be used
for return type 'System.Object'
显然它无法处理值类型的自动装箱和拆箱。有没有办法让这个工作?
对 Expression.Call
的结果调用 Expression.Convert
并将其转换为 object
。这样就会在需要对类型进行装箱的情况下进行装箱操作。