テンプレートの解析と反映

asp.net c# reflection templates
テンプレートの解析と反映

サイトのテンプレートがhtmlファイルで定義されているコンテンツ管理システムをASP.NET/C#で作成しています。 * blocks でhtmlファイルにパラメーターを渡します。 ブロックは [で始まり、] *で終わります。 いくつかの単純なブロックを持つテンプレートの例:

    [Title]



    [Headline]
    [Text]

これで、テンプレートを表すクラスができました。 サンプルテンプレートのクラスは次のようになります。

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);
    }

…​and it is working. I’m using GetProperties() and then Linq instead of
大文字と小文字を区別しないGetProperty。 しかし、ブロック内のパラメーターを使用する場合、別の問題が発生します。 例:垂直メニューを作成したい。 システムのメニューは垂直または水平にできます。

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

そのため、このタイプのブロックは、プロパティから値を抽出するのではなく、メソッドを呼び出して値を抽出することにしました。 例:

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, "(?\\w+)=((?\\w+)|\"(?([^\"]*))\")");

            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);
    }
}

それは機能していますが、より効果的にする方法を探しています。 そして、実際にこれを実装するのが正しい方法かどうかわかりませんか?

ありがとうございました。

  1  1


ベストアンサー

おそらくASP.Netが提供するネイティブテンプレートを使用しますか? つまり、標準の.aspxページを使用してテンプレートを定義し、Server.Executeメソッドを使用してこれらのページで生成された出力をキャプチャします。 サーバーコードブロック(<%=%>)を使用して、1。)コードビハインドによって公開された変数を挿入するか、2。)コードビハインドでメソッドを実行できます。 解析コードを更新する手間が省け、広く認識されているテンプレート形式が提供されます。

1


コード内からトークンをスタイリングするのではなく、実際のテンプレートでトークンのスタイリングを管理することを検討しましたか? たとえば、提案されたアプローチの理想的な候補となる可能性のある方向プロパティがあります。 これにより、トークンの解析を非常に簡単に保つことができます。

0


タイトルとURLをコピーしました