c# - 更改表达式的参数值>
问题描述
假设我有一个看起来像这样的类 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
,但我不确定这是否是我需要的东西。
有什么办法可以实现我想要做的事情吗?
先感谢您
__
更新
我几乎可以在@Guru 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"
推荐阅读
- c - 重复直到用户按下回车
- xpath - 如何迭代使用 sxd_xpath 提取的节点的所有属性?
- php - Laravel 5.8 - 无法使用 Laravel 添加或更新子行
- c# - 如何在 Unity 中自然地将车辆从一个坐标移动到另一个坐标?
- java - 如何保持字符串中特定字符的所有出现(不区分大小写)并使所有非字母字符不受影响?
- sql-server - 如何使用子查询来选择最大值?
- java - “org.hibernate.SessionException:会话已关闭”在极少数情况下
- excel - 删除列中大于数字的单元格
- android-espresso - 如何使用 BySelector Text 在 espresso 中忽略大小写来查找元素
- java - 当我使用 FileInputStream 导出 JAR 文件时出现 FileNotFoundException