Expression.Assign
在 .NET 4 之前不可用。我需要在 .NET 3.5 下使用原始签名实现此方法:
public static BinaryExpression Assign(
Expression left,
Expression right
)
澄清:在某些情况下,我不是在寻找使用这种方法的方法。我需要实施一般情况。
Expression.Assign
在 .NET 4 之前不可用。我需要在 .NET 3.5 下使用原始签名实现此方法:
public static BinaryExpression Assign(
Expression left,
Expression right
)
澄清:在某些情况下,我不是在寻找使用这种方法的方法。我需要实施一般情况。
由于没有 ,因此您无法获得精确的等价物ExpressionType.Assign
,但可以制作类似的东西:
public static class ExpressionEx
{
public static BinaryExpression Assign(Expression left, Expression right)
{
var assign = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign");
var assignExpr = Expression.Add(left, right, assign);
return assignExpr;
}
private static class Assigner<T>
{
public static T Assign(ref T left, T right)
{
return (left = right);
}
}
}
然后您可以使用它来生成分配:
class Foo
{
public int Data
{
get;
set;
}
}
class Program
{
static Action<object, object> MakeSetter(PropertyInfo info)
{
var objectParameter = Expression.Parameter(typeof(object), string.Empty);
var valueParameter = Expression.Parameter(typeof(object), string.Empty);
var setterExpression = Expression.Lambda<Action<object, object>>(
ExpressionEx.Assign(
Expression.Property(
Expression.Convert(objectParameter, info.DeclaringType),
info),
Expression.Convert(valueParameter, info.PropertyType)),
objectParameter,
valueParameter);
return setterExpression.Compile();
}
static void Main()
{
var foo = new Foo();
var property = typeof(Foo).GetProperty("Data");
var setter = MakeSetter(property);
setter(foo, 10);
Console.WriteLine(foo.Data);
}
}
如果你真的不需要BinaryExpression
作为返回类型,你可以使用它Expression.Call
而不是Add
这样它就不会那么hackish。
恐怕你不能。
原因如下:
ExpressionType
枚举不包含Assign
3.5 中的成员。Expression.MakeBinary()
,但该方法被忽略。(生成的 BinaryExpression 具有 standardMethod
或Method
= null。)Method
在实例中赋值——它是只读的并且类是密封的,所以你不能在派生类中解决它。但是由于他们已经将该method
参数包含在 中MakeBinary()
,因此可能仍然存在一些解决方法......我不能 100% 确定这是不可能的。
基于 Konstantin Oznobihin 的破解,这里稍微修改了一个,其中包含MethodCallExpression
而不是 a BinaryExpression
:
public class ExpressionEx
{
public static Expression Assign(Expression left, Expression right)
{
var method = typeof(ExpressionEx).GetMethod("Assign", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(left.Type);
return Expression.Call(method, left, right);
}
private static void Assign<T>(ref T left, T right)
{
left = right;
}
}
Assign
这将创建一个到内部的-method的委托,ExpressionEx
现在可以像这样轻松地使用:
var expr = ExpressionEx.Assign(myInstanceExpression, newValueExpression);