2012-09-02 61 views
1

我試圖用樹完善的String.format CallExpression

調用string.Format我花了一些工作,因爲我的供應params Expression[] _ParameterExpressions不匹配的string.Format簽署該接受object[]現在看來,這將不適用的隱式轉換。

我目前的解決方案是使用

NewArrayExpression _NewArray = Expression.NewArrayInit(typeof(object), _ParameterExpressions.Select(ep => Expression.Convert(ep, typeof(object)))); 

和設置我的代理功能將參數傳遞給string.Format(我需要這個,否則它會說,它無法找到匹配的簽名)

我提供的參數轉換爲 object[]
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()); 

回答

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()(); 
    
+0

我明白了。這就是重點。謝謝! – ipoppo