[英]Field Setter/Getter using Delegate
這是我的簡單測試代碼。 我想在2個對象之間創建字段分配鏈接,並在運行時使用反射通過緩存其setter / getter方法的委托來確定該字段。 但是,以某種方式它不起作用。 分配工作失敗; 也許我犯了一個愚蠢的錯誤。 我哪里錯了?
public static class AssignmentExpression
{
public static Expression Create(Expression left, Expression right)
{
MethodInfo m = typeof(AssignmentExpression)
.GetMethod("AssignTo", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(left.Type);
return Expression.Call( null,m,left, right);
}
private static void AssignTo<T>(ref T left, T right)
{
left = right;
}
}
public class FieldLink
{
protected Delegate srcGetter;
protected Delegate dstSetter;
public FieldLink(FieldInfo srcObject, FieldInfo dstObject)
{
this.srcGetter = FieldLink.createGetter(srcObject);
this.dstSetter = FieldLink.createSetter(dstObject);
}
public void update<T>(T dst, T src)
{
this.dstSetter.DynamicInvoke(dst, this.srcGetter.DynamicInvoke(src));
}
protected static Delegate createGetter(FieldInfo field)
{
ParameterExpression objParm = Expression.Parameter(field.DeclaringType, "obj");
Type delegateType = typeof(Func<,>).MakeGenericType(field.DeclaringType, field.FieldType);
MemberExpression fieldExpr = Expression.Field(objParm, field.Name);
LambdaExpression lambda = Expression.Lambda(delegateType, fieldExpr, objParm);
return lambda.Compile();
}
protected static Delegate createSetter(FieldInfo field)
{
ParameterExpression objParm = Expression.Parameter(field.DeclaringType, "obj");
ParameterExpression valueParm = Expression.Parameter(field.FieldType, "value");
Type delegateType = typeof(Action<,>).MakeGenericType(field.DeclaringType, field.FieldType);
MemberExpression memberExpr = Expression.Field(objParm, field.Name);
Expression assignExpr = AssignmentExpression.Create(memberExpr, valueParm);
LambdaExpression lambda = Expression.Lambda(delegateType, assignExpr, objParm, valueParm);
return lambda.Compile();
}
}
public class Test
{
public int fieldInt = 0;
}
public class TestClass
{
public Test a = new Test();
public Test b = new Test();
public void Start()
{
a.fieldInt = 5;
Debug.Log("before a = " + a.fieldInt + " b = " + b.fieldInt);
FieldLink testLink = new FieldLink(this.a.GetType().GetField("fieldInt"),
this.b.GetType().GetField("fieldInt"));
testLink.update(this.b, this.a);
Debug.Log("after a = " + a.fieldInt + " b = " + b.fieldInt);
//here a.fieldInt should be equal to b.fieldInt, but somehow its unchanged!
}
}
您的代碼似乎可以正常工作,但可能與您的期望不完全一樣。 調用update
您將b.fieldInt
作為left
參數傳遞,並將a.fieldInt
作為right
參數a.fieldInt
; 然后, update
方法將a.fieldInt
(5)的值分配給b.fieldInt
字段,導致兩個對象的fieldInt
值均為5。如果反轉參數,則兩個字段最終都為零。 那不是您所期望的嗎?
順便說一句-也許您還有其他使用自己的AssignmentExpression
類的原因-但您實際上可以替換:
Expression assignExpr = AssignmentExpression.Create(memberExpr, valueParm);
...具有:
Expression assignExpr = Expression.Assign(memberExpr, valueParm);
...您得到相同的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.