Expression.Assign在.Net 3.5中的实现具有相同的签名?

时间:2012-04-12 11:42:56

标签: c# .net-4.0 .net-3.5 expression expression-trees

在.NET 4之前,

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

public static BinaryExpression Assign(
    Expression left,
    Expression right
)

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

3 个答案:

答案 0 :(得分: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。

答案 1 :(得分:0)

我怕你不能。

原因如下:

  1. ExpressionType枚举在3.5中不包含Assign成员。
  2. 我尝试使用错误的ExpressionType并使用我的方法使用Expression.MakeBinary()创建二进制表达式,但该方法被忽略。 (结果BinaryExpression具有标准MethodMethod = null。)
  3. 你不能在实例中指定Method - 它是只读的,并且类是密封的,所以你不能在派生类中解决它。
  4. 但是因为他们已经将method参数包含在MakeBinary()中,所以仍然可能存在一些解决方法......我不是百分之百确定它是不可能的。

答案 2 :(得分:0)

基于Konstantin Oznobihin的洗脱,这是一个含有MethodCallExpression而不是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内创建ExpressionEx - 方法的委托,现在可以像这样轻松使用:

var expr = ExpressionEx.Assign(myInstanceExpression, newValueExpression);