当前位置:  开发笔记 > 编程语言 > 正文

如何在C#表达式树中设置字段值?

如何解决《如何在C#表达式树中设置字段值?》经验,为你挑选了3个好方法。

鉴于:

FieldInfo field = ;
ParameterExpression targetExp = Expression.Parameter(typeof(T), "target");
ParameterExpression valueExp = Expression.Parameter(typeof(string), "value");

如何编译lambda表达式以将"target"参数上的字段设置为"value"?



1> Barry Kelly..:

.Net 4.0:现在有了Expression.Assign,这很容易做到:

FieldInfo field = typeof(T).GetField("fieldName");
ParameterExpression targetExp = Expression.Parameter(typeof(T), "target");
ParameterExpression valueExp = Expression.Parameter(typeof(string), "value");

// Expression.Property can be used here as well
MemberExpression fieldExp = Expression.Field(targetExp, field);
BinaryExpression assignExp = Expression.Assign(fieldExp, valueExp);

var setter = Expression.Lambda>
    (assignExp, targetExp, valueExp).Compile();

setter(subject, "new value");

.Net 3.5:你不能,你必须使用System.Reflection.Emit代替:

class Program
{
    class MyObject
    {
        public int MyField;
    }

    static Action MakeSetter(FieldInfo field)
    {
        DynamicMethod m = new DynamicMethod(
            "setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(Program));
        ILGenerator cg = m.GetILGenerator();

        // arg0. = arg1
        cg.Emit(OpCodes.Ldarg_0);
        cg.Emit(OpCodes.Ldarg_1);
        cg.Emit(OpCodes.Stfld, field);
        cg.Emit(OpCodes.Ret);

        return (Action) m.CreateDelegate(typeof(Action));
    }

    static void Main()
    {
        FieldInfo f = typeof(MyObject).GetField("MyField");

        Action setter = MakeSetter(f);

        var obj = new MyObject();
        obj.MyField = 10;

        setter(obj, 42);

        Console.WriteLine(obj.MyField);
        Console.ReadLine();
    }
}


chakrit - 它更快.

2> Marc Gravell..:

如已经讨论的那样,设置字段是有问题的.你可以(在3.5中)单个方法,例如属性设置器 - 但只能间接地.这得到4.0要容易得多,因为讨论在这里.但是,如果您实际拥有属性(而不是字段),则可以使用以下方法执行以下操作Delegate.CreateDelegate:

using System;
using System.Reflection;
public class Foo
{
    public int Bar { get; set; }
}
static class Program
{
    static void Main()
    {
        MethodInfo method = typeof(Foo).GetProperty("Bar").GetSetMethod();
        Action setter = (Action)
            Delegate.CreateDelegate(typeof(Action), method);

        Foo foo = new Foo();
        setter(foo, 12);
        Console.WriteLine(foo.Bar);
    }
}



3> 小智..:
private static Action CreateSetAccessor(FieldInfo field)
    {
        DynamicMethod setMethod = new DynamicMethod(field.Name, typeof(void), new[] { typeof(object), typeof(object) });
        ILGenerator generator = setMethod.GetILGenerator();
        LocalBuilder local = generator.DeclareLocal(field.DeclaringType);
        generator.Emit(OpCodes.Ldarg_0);
        if (field.DeclaringType.IsValueType)
        {
            generator.Emit(OpCodes.Unbox_Any, field.DeclaringType);
            generator.Emit(OpCodes.Stloc_0, local);
            generator.Emit(OpCodes.Ldloca_S, local);
        }
        else
        {
            generator.Emit(OpCodes.Castclass, field.DeclaringType);
            generator.Emit(OpCodes.Stloc_0, local);
            generator.Emit(OpCodes.Ldloc_0, local);
        }
        generator.Emit(OpCodes.Ldarg_1);
        if (field.FieldType.IsValueType)
        {
            generator.Emit(OpCodes.Unbox_Any, field.FieldType);
        }
        else
        {
            generator.Emit(OpCodes.Castclass, field.FieldType);
        }
        generator.Emit(OpCodes.Stfld, field);
        generator.Emit(OpCodes.Ret);
        return (Action)setMethod.CreateDelegate(typeof(Action));
    }

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有