How do I set a field value in an C# Expression tree?

后端 未结 6 617
野趣味
野趣味 2020-12-02 08:16

Given:

FieldInfo field = ;
ParameterExpression targetExp = Expression.Parameter(typeof(T), \"target\");
ParameterExp         


        
6条回答
  •  盖世英雄少女心
    2020-12-02 09:05

    .Net 4.0 : now that there's Expression.Assign, this is easy to do:

    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 : you can't, you'll have to use System.Reflection.Emit instead:

    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();
        }
    }
    

提交回复
热议问题