我一直在使用下面的代碼緩存,以便快速訪問該功能屬性的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