改变Expression<Func<<string>&gt的参数值。

问题描述 投票:2回答:1

假设我有一个类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

这个错误非常明显,但我似乎找不到一种方法来将参数转换为正确的类型。

我之所以修改代码是因为我不知道参数的数量,所以我试着循环通过它们任何只改变我需要的那些,因为顺序仍然是正确的。

有什么想法吗?

c# .net expression expression-trees func
1个回答
1
投票

你将需要建立一个新的表达式,并将新的所需参数传递给它。

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"
© www.soinside.com 2019 - 2024. All rights reserved.