Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用委托的字段设置器/获取器_C#_Delegates_Mono_Field_Expression Trees - Fatal编程技术网

C# 使用委托的字段设置器/获取器

C# 使用委托的字段设置器/获取器,c#,delegates,mono,field,expression-trees,C#,Delegates,Mono,Field,Expression Trees,这是我的简单测试代码。我想在两个对象之间创建字段分配链接,该字段在运行时使用setter/getter方法的reflection by caching delegate来确定。但是,不知怎么的,它不起作用。任务不起作用;也许我犯了一个愚蠢的错误。我错在哪里 public static class AssignmentExpression { public static Expression Create(Expression left, Expression right) {

这是我的简单测试代码。我想在两个对象之间创建字段分配链接,该字段在运行时使用setter/getter方法的reflection by caching delegate来确定。但是,不知怎么的,它不起作用。任务不起作用;也许我犯了一个愚蠢的错误。我错在哪里

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!
    }
}
公共静态类赋值表达式
{
公共静态表达式创建(表达式左、表达式右)
{
MethodInfo m=typeof(AssignmentExpression)
.GetMethod(“AssignTo”,BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(左.Type);
返回表达式.Call(null、m、left、right);
}
专用静态无效分配(左参考T,右参考T)
{                                                     
左=右;
}
}
公共类字段链接
{
受保护的代理获取程序;
受保护的委托设置器;
公共字段链接(FieldInfo srcObject、FieldInfo dstObject)
{
this.srcGetter=FieldLink.createGetter(srcObject);
this.dstSetter=FieldLink.createSetter(dstObject);
}
公共无效更新(T dst、T src)
{
this.dstSetter.DynamicInvoke(dst,this.srcGetter.DynamicInvoke(src));
}
受保护的静态委托createGetter(FieldInfo字段)
{
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);
返回lambda.Compile();
}
受保护的静态委托createSetter(FieldInfo字段)
{
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);
表达式assignExpr=AssignmentExpression.Create(memberExpr,valueParm);
LambdaExpression lambda=Expression.lambda(delegateType、assignExpr、objParm、valueParm);
返回lambda.Compile();
}
}
公开课考试
{
公共int-fieldInt=0;
}
公共类TestClass
{
公共测试a=新测试();
公共测试b=新测试();
公开作废开始()
{
a、 fieldInt=5;
Debug.Log(“a=“+a.fieldInt+”b=“+b.fieldInt之前”);
FieldLink testLink=new FieldLink(this.a.GetType().GetField(“fieldInt”),
this.b.GetType().GetField(“fieldInt”);
update(this.b,this.a);
Debug.Log(“在a=“+a.fieldInt+”b=“+b.fieldInt”之后);
//这里,a.fieldInt应该等于b.fieldInt,但不知何故它是不变的!
}
}

您的代码似乎正常工作,但可能并不完全符合您的预期。调用
update
时,将
b.fieldInt
作为
left
参数传递,将
a.fieldInt
作为
right
参数传递;然后,
update
方法将
a.fieldInt
(5)的值分配给
b.fieldInt
字段,导致两个对象的
fieldInt
值均为5。如果反转参数,两个字段都将结束为零。这不是你所期望的吗

顺便说一句——也许您使用自己的
AssignmentExpression
类还有其他原因——但实际上您可以替换:

Expression assignExpr = AssignmentExpression.Create(memberExpr, valueParm);
…与:

Expression assignExpr = Expression.Assign(memberExpr, valueParm);

…您将得到相同的结果。

您的代码似乎正常工作,但可能与您的预期不完全一致。调用
update
时,将
b.fieldInt
作为
left
参数传递,将
a.fieldInt
作为
right
参数传递;然后,
update
方法将
a.fieldInt
(5)的值分配给
b.fieldInt
字段,导致两个对象的
fieldInt
值均为5。如果反转参数,两个字段都将结束为零。这不是你所期望的吗

顺便说一句——也许您使用自己的
AssignmentExpression
类还有其他原因——但实际上您可以替换:

Expression assignExpr = AssignmentExpression.Create(memberExpr, valueParm);
…与:

Expression assignExpr = Expression.Assign(memberExpr, valueParm);

…得到相同的结果。

奇怪的是,在我的例子中,在还原参数后,值仍然是相同的。顺便说一句,我的环境是.Net 3.5,因此我没有
表达式.Assign
…使用VS2012.Net 3.5上运行的
AssignmentExpression
类,它仍然适用于我-两者都以5结尾,或者都以0结尾。非常奇怪!哦,不,我使用的是Unity3D环境,它使用的是Mono 2.6.x,它可能是Mono bug?啊,对-我没有可以检查的设置,但这听起来像是一个可能的罪魁祸首。奇怪的是,在我的情况下,在还原参数后,值仍然是相同的。顺便说一句,我的环境是.Net 3.5,因此我没有
表达式.Assign
…使用VS2012.Net 3.5上运行的
AssignmentExpression
类,它仍然适用于我-两者都以5结尾,或者都以0结尾。非常奇怪!哦,不,我使用的是Unity3D环境,它使用的是Mono 2.6.x,可能是Mono bug?啊,对-我没有可以检查的设置,但这听起来很可能是罪魁祸首。