【发布时间】:2010-05-15 16:02:23
【问题描述】:
创建一个返回对象属性值的 lambda 函数相对容易,甚至包括深层属性...
Func<Category, string> getCategoryName = new Func<Category, string>(c => c.Name);
这可以如下调用...
string categoryName = getCategoryName(this.category);
但是,鉴于仅上面的结果函数(或最初用于创建函数的表达式),任何人都可以提供一种简单的方法来创建相反的动作.. .
Action<Category, string> setCategoryName = new Action<Category, string>((c, s) => c.Name = s);
...这将使相同的属性值设置如下?
setCategoryName(this.category, "");
请注意,我正在寻找一种从函数或表达式以编程方式创建动作的方法 - 我希望我已经表明我已经知道如何手动创建它。
我愿意接受适用于 .net 3.5 和 4.0 的答案。
谢谢。
更新:
也许我的问题并不清楚,所以让我试着更清楚地展示我想要做什么。
我有以下方法(我为此问题创建的)...
void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression) {
Func<TObject, TValue> getValue = expression.Compile();
TValue stuff = getValue(obj);
Expression<Action<TObject, TValue>> assignmentExpression = (o, v) => Expression<TObject>.Assign(expression, Expression.Constant(v, typeof(TValue)));
Action<TObject, TValue> setValue = assignmentExpression.Compile();
setValue(obj, stuff);
}
我正在寻找的是如何在代码中创建“assignmentExpression”,以便可以将其编译为 setValue?我认为它与 Expression.Assign 相关,但我根本无法计算出正确的参数组合来完成代码。
最终的结果是能够调用
Category category = *<get object from somewhere>*;
this.DoLambdaStuff(category, c => c.Name);
这又会为 Category 对象的“Name”属性创建一个 getter 和一个 setter。
上面的版本可以编译,但是当我调用 setValue() 时,它会导致 ArgumentException 出现“表达式必须是可写的”。
再次感谢。
【问题讨论】:
-
我真的不明白你的意思是自动而不是手动。但是,如果要设置属性并决定要在运行时设置哪个属性,则应使用反射。此外,您可以使用表达式树来构建运行时 lambda 表达式。