Given:
FieldInfo field = <some valid string field on type T>; ParameterExpression targetExp = Expression.Parameter(typeof(T), "target"); ParameterExpression valueExp = Expression.Parameter(typeof(string), "value");
How do I compile a lambda expression to set the field on the "target" parameter to "value"?
.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<Action<T, string>> (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<T,TValue> MakeSetter<T,TValue>(FieldInfo field) { DynamicMethod m = new DynamicMethod( "setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(Program)); ILGenerator cg = m.GetILGenerator(); // arg0.<field> = arg1 cg.Emit(OpCodes.Ldarg_0); cg.Emit(OpCodes.Ldarg_1); cg.Emit(OpCodes.Stfld, field); cg.Emit(OpCodes.Ret); return (Action<T,TValue>) m.CreateDelegate(typeof(Action<T,TValue>)); } static void Main() { FieldInfo f = typeof(MyObject).GetField("MyField"); Action<MyObject,int> setter = MakeSetter<MyObject,int>(f); var obj = new MyObject(); obj.MyField = 10; setter(obj, 42); Console.WriteLine(obj.MyField); Console.ReadLine(); } }
Setting a field is, as already discussed, problematic. You can can (in 3.5) a single method, such as a property-setter - but only indirectly. This gets much easier in 4.0, as discussed here. However, if you actually have properties (not fields), you can do a lot simply with 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<Foo, int> setter = (Action<Foo, int>) Delegate.CreateDelegate(typeof(Action<Foo, int>), method); Foo foo = new Foo(); setter(foo, 12); Console.WriteLine(foo.Bar); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With