【发布时间】:2016-04-24 04:42:24
【问题描述】:
我一直在使用以下代码来缓存属性 getter/setter 委托,以便快速访问该功能:
class PropertyHelper
{
public static Func<object, object> BuildGetter(PropertyInfo propertyInfo)
{
var method = propertyInfo.GetGetMethod(true);
var obj = Expression.Parameter(typeof(object), "o");
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();
}
public static Action<object, object> BuildSetter(PropertyInfo propertyInfo)
{
var method = propertyInfo.GetSetMethod(true);
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
Expression<Action<object, object>> expr =
Expression.Lambda<Action<object, object>>(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj,
value);
Action<object, object> action = expr.Compile();
return action;
}
}
这在访问类对象的属性时效果很好,但是当我将它用于结构对象时它会失败。例如,考虑以下代码:
public struct LocationStruct
{
public double X { get; set; }
public double Y { get; set; }
}
public class LocationClass
{
public double X { get; set; }
public double Y { get; set; }
}
public class Tester
{
public static void TestSetX()
{
Type locationClassType = typeof(LocationClass);
PropertyInfo xProperty = locationClassType.GetProperty("X");
Action<object, object> setter = PropertyHelper.BuildSetter(xProperty);
LocationStruct testLocationClass = new LocationClass();
setter(testLocationClass, 10.0);
if (testLocationClass.X == 10.0)
{
MessageBox.Show("Worked for the class!");
}
Type locationStructType = typeof(LocationStruct);
xProperty = locationStructType.GetProperty("X");
setter = PropertyHelper.BuildSetter(xProperty);
LocationStruct testLocationStruct = new LocationStruct();
setter(testLocationStruct, 10.0);
if (testLocationStruct.X != 10.0)
{
MessageBox.Show("Didn't work for the struct!");
}
}
}
第一部分起作用,将 testLocationClass 的 X 值设置为 10。但是,由于 LocationStruct 是一个结构,testLocationStruct 是按值传递的,该值(在委托调用的方法内部)将其 X 设置为10,但上面代码块中的testLocationStruct对象保持不变。
因此,我需要一种访问结构对象属性的方法,类似于上述方法(仅适用于类对象的属性)。我尝试使用“按引用传递”模式来完成此操作,但我无法让它发挥作用。
谁能提供类似的 BuildGetter 和 BuildSetter 方法来缓存结构属性值的 getter/setter 委托?
【问题讨论】:
-
快速说明:这些不称为 lambda 表达式,只是表达式或表达式树。 Lambda 更多地指的是闭包,即 C# 中的匿名函数。
-
Rgr...感谢您的注意。我将更改我的标题和标签。
-
请详细说明这对值类型(结构)不起作用。您是否遇到处理盒装值类型的问题?如果是这样,是否可以通过更改代码使其通用而不是假设 System.Object 来解决它?您应该发布代码,演示如何将您的实现用于值类型,清楚地表明这对您不起作用。
-
彼得,感谢您的评论。我添加了更多细节和示例。
标签: c# struct linq-expressions propertyinfo