реализация механизма шаблонов

В настоящее время я создаю этот небольшой механизм шаблонов. Он принимает строку, содержащую шаблон в параметре, и словарь «тегов, значений» для заполнения шаблона.

В движке я понятия не имею, какие теги будут в шаблоне, а какие нет.

В настоящее время я повторяю (foreach) словарь, анализирую свою строку, которую я поместил в построитель строк, и заменяю теги в шаблоне их соответствующим значением.

Есть ли более эффективный/удобный способ сделать это? Я знаю, что основным недостатком здесь является то, что построитель строк каждый раз анализируется полностью для каждого тега, что довольно плохо...

(Я также проверяю, хотя и не включен в образец, после процесса, что мой шаблон больше не содержит никаких тегов. Все они отформатированы одинаково: @@tag@@)

//Dictionary<string, string> tagsValueCorrespondence;
//string template;

StringBuilder outputBuilder = new StringBuilder(template);
foreach (string tag in tagsValueCorrespondence.Keys)
{
    outputBuilder.Replace(tag, tagsValueCorrespondence[tag]);
}

template = outputBuilder.ToString();

Ответы:

@Марк:

string template = "Some @@foobar@@ text in a @@bar@@ template";
StringDictionary data = new StringDictionary();
data.Add("foo", "value1");
data.Add("bar", "value2");
data.Add("foo2bar", "value3");

Вывод: "Некоторый текст в шаблоне value2"

вместо: "Некоторый текст @@foobar@@ в шаблоне value2"


person Community    schedule 27.05.2009    source источник
comment
Хорошо... используйте Dictionary‹string,string› вместо StringDictionary, и он выдаст ошибку для пропущенных ключей... не сложно.   -  person Marc Gravell    schedule 02.06.2009


Ответы (3)


arrow_upward
1
arrow_downward

Как насчет Regex и MatchEvaluator? Вот так:

string template = "Some @@Foo@@ text in a @@Bar@@ template";
StringDictionary data = new StringDictionary();
data.Add("foo", "random");
data.Add("bar", "regex");
string result = Regex.Replace(template, @"@@([^@]+)@@", delegate(Match match)
{
    string key = match.Groups[1].Value;
    return data[key];
});
person Marc Gravell    schedule 27.05.2009
comment
Совершенно бесполезно, как только шаблон пойдет не так (например, еще один @ неуместен). Я буду придерживаться своего метода замены, если у кого-то другого нет лучшего решения... - person ; 01.06.2009
comment
Редактировать: На самом деле, это тоже бесполезно, если у вас есть такой тег @@foo2 bar@@. Если в шаблоне у вас есть что-то вроде @@foo bar@@, оно заменяется пробелом. Плохое решение для обнаружения ошибок - person ; 01.06.2009
comment
Можете ли вы расширить по любому пункту? foo bar по-прежнему должен работать нормально ... и я тоже не понял вашего другого @ неуместного пункта. Любой пример? - person Marc Gravell; 01.06.2009

arrow_upward
0
arrow_downward

Вот пример кода, который вы можете использовать в качестве отправной точки:

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

class Program {
    static void Main() {
        var template = " @@3@@  @@2@@ @@__@@ @@Test ZZ@@";
        var replacement = new Dictionary<string, string> {
                {"1", "Value 1"},
                {"2", "Value 2"},
                {"Test ZZ", "Value 3"},
            };
        var r = new Regex("@@(?<name>.+?)@@");
        var result = r.Replace(template, m => {
            var key = m.Groups["name"].Value;
            string val;
            if (replacement.TryGetValue(key, out val))
                return val;
            else
                return m.Value;
        });
        Console.WriteLine(result);
    }
}
person Lloyd    schedule 27.05.2009

arrow_upward
0
arrow_downward

Вы можете изменить реализацию формата моностроки, чтобы она принимала ваш строковый словарь. Например, http://github.com/wallymathieu/cscommon/blob/master/library/StringUtils.cs

person Community    schedule 07.12.2010