假设我有一个类Item,它看起来是这样的
public class Item
{
// ..
Expression<Func<string>> Callback {get; set;}
}
Item
定义了一个名为 Callback
可以这样使用
public string TestFunction(string ident, DateTime value1, DateTime value2)
{
return string.Join(";", ident, value1, value2);
}
// ..
Item x = new Item();
x.Callback = () => TestFunction("Hello there", DateTime.Now.Date, DateTime.Now);
Console.WriteLine(x.Callback.Compile().Invoke()); // prints the expected output
这样就很好用了。现在,我想做的是更改 DateTime
参数。
我已经知道如何获取参数。
MethodCallExpression body = (MethodCallExpression)x.Callback.Body;
foreach(ConstantExpression arg in body.Arguments) {
if(arg.Type == typeof(DateTime)) {
//arg.Value = => READONLY!
}
}
但是,我不能给这个参数赋予一个新的值... arg.Value
因为没有设置器。
似乎有一种叫做 ExpressionVisitor
但我不确定这是不是我需要的东西。
有什么办法可以实现我想做的事情吗?
先谢谢你
__
更新
在@Stron大师的帮助下,我几乎把它弄好了,但还是有一个小问题。
这段代码完全可以正常工作。
var newParams = new[] { Expression.Constant("testIdent"), Expression.Constant(DateTime.Now), Expression.Constant(DateTime.Now) };
但是下面的代码却抛出了一个
Expression of type 'System.Linq.Expressions.ConstantExpression' cannot be used for parameter of type 'System.String' of method 'System.String TestFunction(System.String, System.DateTime, System.DateTime)'
异常。
List<ConstantExpression> para = new List<ConstantExpression>();
foreach (var arg in body.Arguments) {
if (arg.Type == typeof(DateTime)) {
para.Add(Expression.Constant(DateTime.Now));
continue;
}
para.Add(Expression.Constant(arg));
}
var exprBody = Expression.Call(body.Object, body.Method, para); // Exception is thrown here
这个错误非常明显,但我似乎找不到一种方法来将参数转换为正确的类型。
我之所以修改代码是因为我不知道参数的数量,所以我试着循环通过它们任何只改变我需要的那些,因为顺序仍然是正确的。
有什么想法吗?
你将需要建立一个新的表达式,并将新的所需参数传递给它。
MethodCallExpression body = (MethodCallExpression)x.Callback.Body;
var newParams = new[] { Expression.Constant("NEW "), Expression.Constant(DateTime.Now), Expression.Constant(DateTime.Now)};
var exprBody = Expression.Call(body.Object, body.Method, newParams );
var newExpr = Expression.Lambda<Func<string>>(exprBody);
var newFunc = newExpr.Compile();
Console.WriteLine(newFunc()); // "NEW ;03-Jun-20 5:07:16 PM;03-Jun-20 5:07:16 PM"