在.NET 3.5中,Expression.Assign的等效方法是什么?

3
在 .Net 4.0 中,微软添加了 Expression.Assign。但是我只能使用 3.5 版本。我正在尝试编写一种方法来设置对象属性,但到目前为止,我没有取得太大的进展。我可以这样做:
public void Assign(object instance, PropertyInfo pi, object value)
{
    pi.SetValue(instance, value, null);
}

但我想避免使用反射的开销!ref不能与属性一起使用。这可行吗?


你能给一个你想要实现的例子吗? - Eamon Nerbonne
1个回答

8

鉴于您试图避免反射的开销但涉及表达式树,我假设您正在尝试将表达式编译为委托以设置属性。

所有属性在背后都是get和set方法。这些可以被调用-在.NET 3.5表达式树中可以使用Expression.Call完成。例如:

class Test{ public int X {get;set;} }

//...elsewhere
var xPropSetter = typeof(Test)
    .GetProperty("X",BindingFlags.Instance|BindingFlags.Public)
    .GetSetMethod();
var newValPar=Expression.Parameter(typeof(int));
var objectPar=Expression.Parameter(typeof(Test));
var callExpr=Expression.Call(objectPar, xPropSetter, newValPar);
var setterAction = (Action<Test,int>)
    Expression.Lambda(callExpr, objectPar, newValPar).Compile();
Test val = new Test();
Console.WriteLine(val.X);//0
setterLambda(val,42);
Console.WriteLine(val.X);//42

请注意,如果您只想要一个委托来设置值,您也可以完全不使用表达式树创建委托:
var setterAction = (Action<Test,int>)
    Delegate.CreateDelegate(typeof(Action<Test,int>), xPropSetter);

你知道在需要给Lambda的ref或out参数赋值时,有没有替代Expression.Assign的方法吗?我找不到这样的方法。 - Ark-kun
我怀疑这是不可能的。然而,作为一种解决方法,你可以创建一些帮助方法,例如 static void SetRef<T>(ref T reference, T val) {reference=val;} 并简单地调用它。它可能会稍微慢一点,但你甚至可能会有运气,发现 JIT 可以内联它——它是内联的完美候选者,总之…… - Eamon Nerbonne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接