这是我在这里找到的另一个版本:http ://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1
对此的任何解决方案都将涉及反射,这不太理想,但这是他的代码,解决了其他一些主要的性能问题。(没有错误检查。如果你愿意,可以添加它。):
1) 使用直接运行时反射,没有 DataBinder 开销
2) 不使用正则表达式,使用单遍解析和状态。
3) 不将字符串转换为中间字符串,然后再将其转换为最终格式。
4) 使用单个 StringBuilder 分配和连接,而不是在所有地方更新字符串并将它们连接成新字符串。
5) 消除了为 n 次替换操作调用委托的堆栈开销。
6)通常是单次通过,将以相对线性的方式扩展(每个道具查找和嵌套道具查找仍有一些成本,但就是这样。)
public static string FormatWith(this string format, object source)
{
StringBuilder sbResult = new StringBuilder(format.Length);
StringBuilder sbCurrentTerm = new StringBuilder();
char[] formatChars = format.ToCharArray();
bool inTerm = false;
object currentPropValue = source;
for (int i = 0; i < format.Length; i++)
{
if (formatChars[i] == '{')
inTerm = true;
else if (formatChars[i] == '}')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
sbCurrentTerm.Clear();
inTerm = false;
currentPropValue = source;
}
else if (inTerm)
{
if (formatChars[i] == '.')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
currentPropValue = pi.GetValue(source, null);
sbCurrentTerm.Clear();
}
else
sbCurrentTerm.Append(formatChars[i]);
}
else
sbResult.Append(formatChars[i]);
}
return sbResult.ToString();
}