C# 更改表达式的参数值<;Func<&书信电报;字符串>&燃气轮机;
假设我有一个类项目,看起来像这样C# 更改表达式的参数值<;Func<&书信电报;字符串>&燃气轮机;,c#,.net,expression,expression-trees,func,C#,.net,Expression,Expression Trees,Func,假设我有一个类项目,看起来像这样 public class Item { // .. Expression<Func<string>> Callback {get; set;} } public string TestFunction(string ident, DateTime value1, DateTime value2) { return string.Join(";", ident, value1, value2); } // ..
public class Item
{
// ..
Expression<Func<string>> Callback {get; set;}
}
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
分配新值,因为它没有setter
似乎有一种叫做ExpressionVisitor
的东西,但我不确定这是否是我需要的
有没有办法实现我的目标
先谢谢你
__
更新
我几乎可以在@Guru Stron help中使用它,但仍然有一个小问题
这段代码工作得非常好:
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
List para=新列表();
foreach(body.Arguments中的变量arg){
if(arg.Type==typeof(DateTime)){
para.Add(Expression.Constant(DateTime.Now));
继续;
}
添加(表达式常数(arg));
}
var exprBody=Expression.Call(body.Object,body.Method,para);//这里抛出异常
错误很明显,但我似乎找不到将参数转换为正确类型的方法
我更改代码的原因是因为我不知道参数的数量,所以我尝试在它们之间循环任何只更改我需要的参数,因为顺序仍然正确
有什么想法吗?您需要构建一个新的表达式,并向其传递新的所需参数:
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"
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(exprBody);
var newFunc=newExpr.Compile();
Console.WriteLine(newFunc());//“新建;20年6月3日下午5:07:16;20年6月3日下午5:07:16”
@Shawn很乐意帮忙!只是出于兴趣:像.Compile
这样的调用是否被缓存?我记得反射环境中的某些调用将被缓存,所以这里可能也是这样。@Shawn AFAIK不,您需要自己缓存它们。好的,谢谢。实际上我遇到了一个新问题,我已经更新了帖子。你也能看一下吗?@Shawn将para
更改为var para=new List()代码>和段落添加(表达式常数(arg))代码>至段落添加(arg)代码>