我正在尝试使用Tree
来调用string.Format
由于我的供应params Expression[] _ParameterExpressions
与string.Format
的签名不匹配,接受object[]
它似乎不会应用隐式转化,因此我花了一些工作。
我目前的解决方案是使用
将我提供的参数转换为object[]
NewArrayExpression _NewArray = Expression.NewArrayInit(typeof(object), _ParameterExpressions.Select(ep => Expression.Convert(ep, typeof(object))));
并设置我的代理函数将参数传递给string.Format
(我需要这个,否则会说找不到匹配的签名)
static string ReplaceParameters(string format, params object[] obj)
{
return string.Format(format, obj);
}
static IEnumerable<Expression> ReplaceStringExpression(Expression exp)
{
yield return exp;
yield return _NewArray;
}
最后我的电话
ConstantExpression ce = Expression.Constant(orginalString, typeof(string));
MethodCallExpression me = Expression.Call(typeof(RuleParser), "ReplaceParameters", null,
ReplaceStringExpression(ce).ToArray());
表达式有效但我不太喜欢创建包含额外装箱过程的新数组的想法。我认为这种简单的函数调用过度了。
如何改善此string.Format
电话?
==========
修改
我的学习取得了一些进展。我现在可以抛弃ReplaceParameters
但仍然不喜欢创建对象数组_NewArray
MethodCallExpression me = Expression.Call(
typeof(string).GetMethod("Format", new Type[2] { typeof(string), typeof(object[]) }),
ReplaceStringExpression(ce).ToArray());
答案 0 :(得分:2)
当ExpressionTree由编译器创建时 - 它将包含所有隐式所需的转换,以使选定的方法超载工作
Expression<Func<string>> compilerFactoredExpressionTree = () => string.Format("{0} and {1} and {2} and {3}", 1, "text", true, 2);
// test
// "1 and text and True and 2"
string s = compilerFactoredExpressionTree.Compile()();
// ArrayInit(Convert(1), Convert("text", Convert(2)))
Expression methodArgs = ((MethodCallExpression)compilerFactoredExpressionTree.Body).Arguments[1];
如果您手动构建ExpressionTree - 您需要自己充当编译器 - 手动插入转换或最初声明具有所需类型的值
var parameters = new Expression[]
{
Expression.Constant(1, typeof(object)),
Expression.Constant("text", typeof(object)),
Expression.Constant(true, typeof(object)),
Expression.Constant(2, typeof(object)),
};
var mi = new Func<string, object[], string>(string.Format).Method;
var callStringFormat = Expression.Call(mi, Expression.Constant("{0} and {1} and {2} and {3}"), Expression.NewArrayInit(typeof(object), parameters));
// "1 and text and True and 2"
var lambda = Expression.Lambda<Func<string>>(callStringFormat);
var r = lambda.Compile()();