Разбор и отражение шаблона - PullRequest
1 голос
/ 16 ноября 2009

Я пишу систему управления контентом в ASP.NET/C#, шаблон сайта которой определен в html-файле. Я передаю параметры в HTML-файл с blocks . Блок начинается с [ и заканчивается ] . Пример шаблона с несколькими простыми блоками:

<html>
<head>
    <title>[Title]</title>
    <meta name="description" content="[Description]" />
</head>
<body>
    <h1>[Headline]</h1>
    <p>[Text]</p>
</body>  
</html>

Теперь у меня есть класс, который представляет шаблон. Класс для примера шаблона выглядит следующим образом:

public class MyTemplate
{
    public string Title
    {
        get;
        set;
    }

    public string Description
    {
        get;
        set;
    }

    public string Headline
    {
        get;
        set;          
    }

    public string Text
    {
        get;
        set;          
    }
}

Класс может быть классом, который я пишу, классом, сгенерированным Linq To SQL, или просто любым классом.

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

    public static string ParseTemplateFromObject(string input, object obj)
    {
        return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
        {
            var blockName = match.Result("$1");

            return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase))
                .GetValue(obj, null).ToString();

        }), RegexOptions.Multiline);
    }

... и это работает. Я использую GetProperties (), а затем Linq вместо GetProperty, чтобы предотвратить чувствительность к регистру. Но теперь у меня есть другая проблема, когда я хочу использовать параметры в блоке. Например: я хочу создать вертикальное меню. Меню в системе может быть вертикальным или горизонтальным:

[Menu Id=1, Direction="Vertical"]

Итак, я решил, что этот тип блока вызывает метод и извлекает его значение вместо извлечения значения из его свойства. Пример: * +1021 *

public class MyTemplate
{
    ...
    public string Menu(int id, string direction)
    {
        string menu = ...;
        return menu;
    }
}

Я расширил ParseTemplateFromObject для поддержки этого:

    public static string ParseTemplateFromObject(string input, object obj)
    {
        return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
        {
            var blockName = match.Result("$1");

            var m = Regex.Match(blockName, "(?<Name>\\w+)=((?<Value>\\w+)|\"(?<Value>([^\"]*))\")");

            if (m.Captures.Count > 0)
            {
                var method = obj.GetType().GetMethods().Single(p => p.Name.Equals(blockName.Substring(0, blockName.IndexOf(' '))
                    , StringComparison.OrdinalIgnoreCase));

                var methodParameters = method.GetParameters();
                var parameters = new object[methodParameters.Length];

                while (m.Success)
                {
                    var name = m.Groups["Name"].Value;
                    var value = m.Groups["Value"].Value;

                    var methodParameter = methodParameters.Single(p => p.Name.ToLower() == name.ToLower());
                    parameters[methodParameter.Position] =
                        Convert.ChangeType(value, methodParameter.ParameterType);

                    m = m.NextMatch();
                }

                return method.Invoke(obj, parameters).ToString();
            }
            else
            {
                return obj.GetType().GetProperties().SingleOrDefault(p => p.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase))
                    .GetValue(obj, null).ToString();

            }
        }), RegexOptions.Multiline);
    }
}

Это работает, но я ищу способы сделать его более эффективным. И я не знаю, действительно ли это правильный способ реализовать это?

Спасибо.

Ответы [ 2 ]

1 голос
/ 16 ноября 2009

Возможно, использовать нативный шаблон, предоставляемый ASP.Net? То есть, определите ваши шаблоны, используя стандартные страницы .aspx, а затем используйте метод Server.Execute для захвата вывода, сгенерированного этими страницами. Вы сможете использовать серверные кодовые блоки (<% =%>), чтобы либо 1.) Вставить переменные, предоставляемые кодом позади, либо 2.) выполнить методы в коде позади. Избавит вас от необходимости обновлять код анализа и предоставит широко признанный шаблонный формат.

0 голосов
/ 16 ноября 2009

Рассматривали ли вы управление стилизацией токенов в реальном шаблоне, а не стилизацию из кода? Например, у вас есть свойство направления, которое может быть идеальным кандидатом для моего предложенного подхода. Таким образом, вы можете сделать анализ токенов очень простым.

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