我一直在使用下面的代码缓存,以便快速访问该功能属性的getter/setter代表:使用表达式在C#访问结构特性
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表达式,只是表达式或表达式树。 Lambdas更多地指的是闭包,即C#中的匿名函数。 – metacubed 2014-10-30 01:21:33
Rgr ... thx注释。我会改变我的标题和标签。 – FTLPhysicsGuy 2014-10-30 01:29:01
请详细说明这不适用于值类型(结构)。你是否遇到了处理盒装值类型的问题?如果是这样,它可以通过更改您的代码,以便它通用而不是假定System.Object?您应该发布代码,演示如何使用您的实现值类型,清楚地显示如何不适合你。 – 2014-10-30 01:43:31