Какой подход к шаблонированию в C # мне следует использовать? - PullRequest
6 голосов
/ 06 ноября 2011

У меня есть шаблоны, которые хранятся в базе данных, и данные JSON, которые преобразуются в словарь в C #.

Пример:

Шаблон: "Привет {FirstName}"

Данные: "{FirstName: 'Jack'}"

Это легко работает с одним уровнем данных с помощью регулярного выражения для извлечения чего-либо внутри {} в шаблоне.

То, что я хочу, я хотел бы иметь возможность углубиться в JSON, чем первый слой.

Пример:

Шаблон: "Привет {Имя: {Первый}}" "

Данные: "{Имя: {Первый:" Джек ", Последний:" Смит "}}"

Какой подход мне выбрать?(и некоторые рекомендации о том, с чего начать с выбора)

  1. Регулярное выражение
  2. Не использовать JSON в шаблоне (в пользу xslt или чего-то подобного)
  3. Что-то еще

Я также хотел бы иметь возможность просматривать данные в шаблоне, но я совершенно не представляю, с чего начать!

Спасибо, куча

Ответы [ 4 ]

4 голосов
/ 06 ноября 2011

Вам повезло! SmartFormat делает именно так, как вы описываете. Это легкая утилита форматирования строк с открытым исходным кодом.

Он поддерживает именованные заполнители :

var template = " {Name:{Last}, {First}} ";

var data = new { Name = new { First="Dwight", Last="Schrute" } };

var result = Smart.Format(template, data);
// Outputs: " Schrute, Dwight " SURPRISE!

Также поддерживается форматирование списка :

var template = " {People:{}|, |, and} ";

var data = new { People = new[]{ "Dwight", "Michael", "Jim", "Pam" } };

var result = Smart.Format(template, data);
// Outputs: " Dwight, Michael, Jim, and Pam "

Вы можете проверить модульные тесты для Именованных заполнителей и Список форматеров , чтобы увидеть еще много примеров!

Он даже имеет несколько форм обработки ошибок (игнорирование ошибок, ошибок вывода, ошибок выброса).

Примечание: именованная метка-заполнитель использует поиск по отражению и / или словарю, поэтому вы можете десериализовать JSON в объекты C # или вложенные Dictionaries, и это будет отлично работать!

2 голосов
/ 06 ноября 2011

Вот как я бы это сделал:

Измените ваш шаблон на этот формат Hi {Name.First}

Теперь создайте JavaScriptSerializer для преобразования JSON в Dictionary<string, object>

JavaScriptSerializer jss = new JavaScriptSerializer();
dynamic d = jss.Deserialize(data, typeof(object));

Теперь переменная d содержит значения вашего JSON в словаре.

Имея это, вы можете запустить свой шаблон для регулярного выражения, чтобы рекурсивно заменить {X.Y.Z.N} на ключи словаря.

Полный пример:

public void Test()
{
    // Your template is simpler
    string template = "Hi {Name.First}";

    // some JSON
    string data = @"{""Name"":{""First"":""Jack"",""Last"":""Smith""}}";

    JavaScriptSerializer jss = new JavaScriptSerializer();

    // now `d` contains all the values you need, in a dictionary
    dynamic d = jss.Deserialize(data, typeof(object));

    // running your template against a regex to
    // extract the tokens that need to be replaced
    var result = Regex.Replace(template, @"{?{([^}]+)}?}", (m) =>
        {
            // Skip escape values (ex: {{escaped value}} )
            if (m.Value.StartsWith("{{"))
                return m.Value;

            // split the token by `.` to run against the dictionary
            var pieces = m.Groups[1].Value.Split('.');
            dynamic value = d;

            // go after all the pieces, recursively going inside
            // ex: "Name.First"

            // Step 1 (value = value["Name"])
            //    value = new Dictionary<string, object>
            //    {
            //        { "First": "Jack" }, { "Last": "Smith" }
            //    };

            // Step 2 (value = value["First"])
            //    value = "Jack"

            foreach (var piece in pieces)
            {
                value = value[piece]; // go inside each time
            }

            return value;
        });
}

Я не обработал исключения (например, значение не может быть найдено), вы можете обработать этот случай и вернуть соответствующее значение, если оно не былонайденный.m.Value для необработанного значения или m.Groups[1].Value для строки между {}.

2 голосов
/ 06 ноября 2011

Задумывались ли вы об использовании Javascript в качестве языка сценариев? Я имел большой успех с Jint , хотя стоимость запуска высока. Другой вариант - Юрский , который я сам не использовал.

Если у вас есть веб-приложение, возможно, вам подойдет Razor, см. Здесь .

Использование Regex или любого вида синтаксического анализа строк может, конечно, работать на тривиальные вещи, но может стать болезненным, когда вам нужна логика или даже просто базовые иерархии. Если вы десериализуете свой JSON во вложенные словари, вы можете создать сравнительно легко парсер:

// Untested and error prone, just to illustrate the concept
var parts = "parentObj.childObj.property".split('.');
Dictionary<object,object> current = yourDeserializedObject;
foreach(var key in parts.Take(parts.Length-1)){
    current = current[key];
}
var value = current[parts.Last()];

Только что вы делаете, не делайте XSLT. Действительно, если XSLT является ответом, то вопрос, должно быть, был действительно отчаянным:)

1 голос
/ 06 ноября 2011

Почему не мы nvelocity или что-то еще?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...