1

string.Formatツリーを使用 して電話をかけようとしています

私の供給が暗黙の変換を適用しないように見える署名params Expression[] _ParameterExpressionsと一致しないため、少し作業が必要でした。string.Formatobject[]

私の現在の解決策は、提供されたパラメータを次のように変換すること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());
4

1 に答える 1

2
  1. 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];
    
  2. 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()();
    
于 2012-09-02T12:22:10.047 に答える