Подумав об этом, я понял, чего на самом деле хотел, так это того, чтобы String.Format() принимал IDictionary в качестве аргумента и чтобы шаблоны можно было писать с использованием имен вместо индексов.
Для подстановок строк с большим количеством возможных ключей/значений номера индексов приводят к неразборчивым шаблонам строк, а в некоторых случаях вы можете даже не знать, какие элементы будут иметь какой номер, поэтому я придумал следующее расширение:
https://gist.github.com/896724
По сути, это позволяет вам использовать строковые шаблоны с именами вместо чисел и словарь вместо массива, а также дает вам все другие хорошие функции String.Format(), позволяя использовать пользовательский IFormatProvider, если это необходимо, и позволяя использование всего обычного синтаксиса форматирования — точности, длины и т. д.
Отличным примером является пример, приведенный в справочном материале для String.Format. о том, как шаблоны со многими пронумерованными элементами становятся совершенно неразборчивыми — портируя этот пример для использования этого нового метода расширения, вы получаете что-то вроде этого:
var replacements = new Dictionary<String, object>()
{
{ "date1", new DateTime(2009, 7, 1) },
{ "hiTime", new TimeSpan(14, 17, 32) },
{ "hiTemp", 62.1m },
{ "loTime", new TimeSpan(3, 16, 10) },
{ "loTemp", 54.8m }
};
var template =
"Temperature on {date1:d}:\n{hiTime,11}: {hiTemp} degrees (hi)\n{loTime,11}: {loTemp} degrees (lo)";
var result = template.Subtitute(replacements);
Как кто-то указал, если то, что вы пишете, должно быть сильно оптимизировано, не используйте что-то подобное - если вам нужно форматировать таким образом миллионы строк в цикле, накладные расходы памяти и производительности могут быть значительными.
С другой стороны, если вы беспокоитесь о написании разборчивого, поддерживаемого кода, и если вы выполняете, скажем, кучу операций с базой данных, по большому счету, эта функция не добавит каких-либо значительных накладных расходов.
...
Для удобства я попытался добавить метод, который принимал бы анонимный объект вместо словаря:
public static String Substitute(this String template, object obj)
{
return Substitute(
template,
obj.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(obj, null))
);
}
По какой-то причине это не работает — передача анонимного объекта, такого как new { name: "value" }
, этому методу расширения дает сообщение об ошибке времени компиляции, в котором говорится, что лучшим совпадением является версия IDictionary этого метода. Не знаю, как это исправить. (кто угодно?)
person
mindplay.dk
schedule
31.03.2011