The*_*edi 40 c# lambda expression-trees
鉴于:
FieldInfo field = <some valid string field on type T>;
ParameterExpression targetExp = Expression.Parameter(typeof(T), "target");
ParameterExpression valueExp = Expression.Parameter(typeof(string), "value");
Run Code Online (Sandbox Code Playgroud)
如何编译lambda表达式以将"target"参数上的字段设置为"value"?
Bar*_*lly 71
.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<Action<T, string>>
(assignExp, targetExp, valueExp).Compile();
setter(subject, "new value");
Run Code Online (Sandbox Code Playgroud)
.Net 3.5:你不能,你必须使用System.Reflection.Emit代替:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 23
如已经讨论的那样,设置字段是有问题的.你可以(在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<Foo, int> setter = (Action<Foo, int>)
Delegate.CreateDelegate(typeof(Action<Foo, int>), method);
Foo foo = new Foo();
setter(foo, 12);
Console.WriteLine(foo.Bar);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
private static Action<object, object> 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<object, object>)setMethod.CreateDelegate(typeof(Action<object, object>));
}
Run Code Online (Sandbox Code Playgroud)