3

Expression.Assign在 .NET 4 之前不可用。我需要在 .NET 3.5 下使用原始签名实现此方法:

public static BinaryExpression Assign(
    Expression left,
    Expression right
)

澄清:在某些情况下,我不是在寻找使用这种方法的方法。我需要实施一般情况。

4

3 回答 3

6

由于没有 ,因此您无法获得精确的等价物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。

于 2012-04-12T12:54:18.500 回答
0

恐怕你不能。

原因如下:

  1. ExpressionType枚举不包含Assign3.5 中的成员。
  2. 我尝试使用错误的 ExpressionType 并使用我的方法创建二进制表达式Expression.MakeBinary(),但该方法被忽略。(生成的 BinaryExpression 具有 standardMethodMethod= null。)
  3. 你不能Method在实例中赋值——它是只读的并且类是密封的,所以你不能在派生类中解决它。

但是由于他们已经将该method参数包含在 中MakeBinary(),因此可能仍然存在一些解决方法......我不能 100% 确定这是不可能的。

于 2012-04-12T12:34:16.863 回答
0

基于 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);
于 2017-12-05T17:04:39.317 回答