それで、Razorで厳密に型指定されたテンプレートエンジンを作成することにしました。
かみそり
それを逃した人にとって、Razorは非常にエレガントなマークアップ言語であり、C#またはVBが組み込まれています。 ASP.NET MVCおよびWebMatrixで使用されます。
スコット・ガスリーがすでに私のためにそれをしてくれたので、私はその素晴らしい特性のすべてをペイントしません、そして彼らはそれをハブレに移しさえしました。
重要なことは、 強く型付けされており、 IntelliSenseを含むVisual Studioで優れたサポートを持っていることです。
また、 ASP.NET MVCを使用して.NetでWebプロジェクトを開発し、Razorで表現を記述しています。これは私にとって理想的な選択肢です。 さらに、デューデリジェンスにより、コードの書き直しをなくすことができます-サーバーとクライアントで同じテンプレートを使用します。
MVCの外でRazorを使用することは大きな問題ではありませんが、生成されるコードはC#であり、JavaScriptが必要です。 そして、ここで私の助けになりました...
シャープキット
この素晴らしいツールは、何らかの理由で、 Habrによって無視されます 。 C#コードをJavaScriptに変換できます。
たとえば、
using SharpKit.JavaScript; using SharpKit.jQuery; namespace Namespace { [JsType(JsMode.Global)] public class MyPageClient : jQueryContext { public static void Hello(string name) { J(document.body).append(J("<h1/>").text("Hello, " + name.ToUpper())); } } }
になります
function Hello(name) { $(document.body).append($("<h1/>").text("Hello, " + name.toUpperCase())); };
プロジェクトの公式Webサイトには、許容できるドキュメントがあります。 オンライン変換で遊ぶこともできます 。
SharpKitは支払われますが、間違いなくお金の価値があります。 オープンソースプロジェクトの場合、無料のライセンスを取得できます。 商用の場合は、最大2500行のJavaScriptコードを無料で変換できます。これで十分な場合もあります。
ところで、私はJavaScriptに精通していますが、SharpKitを長い間使用しているので、アドバイスします。 それでも、コンパイル段階で型、通常のインテリセンス、エラーチェックを使用して記述する方がはるかに便利です。
私は気が散りましたが、ご存知のように、SharpKitを使用して、最初にC#に変換されたRazorテンプレートがJavaScriptに変換されます。
Msbuild
さて、プロジェクトのアセンブリ中にこれを行うために、タスクを実装したMSBuildを介してすべてを統合することにしました。
そして今、私はプロジェクトを提示します
SharpKit Razor
はい、元の名前は思いつきませんでした。
CodePlexのプロジェクトの公式サイト
ええ、私は英語で説明を与えられましたが、 Googleはまだ私を理解していません 。
これまでのところ、ソースコードのみがデモされています。
そして今、より詳細に-コードで、しかしより
ええ、はい、これはハブラーです、あなたはすべての内臓を消化する必要があります。 すべてがどのように実装されているかをまだ理解していない人にのみ読んでください。
Razorのベース
Razorエンジンがコードを処理するとき、それはそのようなものからのものです
@inherit MyBase<string[]> <ul> @foreach (var item in Model) { <li>@item</li> } </ul>
出力は、次のようなクラスを生成します。
namespace MyNamespace { public class MyView: MyBase<string[]> { public override void Execute() { WriteLiteral("<ul>\r\n"); foreach (var item in Model) { WriteLiteral("\t<li>"); Write(item); WriteLiteral("</li>\r\n"); } WriteLiteral("</ul>"); } } }
そのため、実行できるように基本クラスを作成し(Executeメソッド)、出力ストリームにデータを書き込みます(シールド-Writeメソッド、非シールド-WriteLiteralメソッド)。
さらに、プレゼンテーションクラスを一般的な形式で操作しやすくするために、IRenderingAreaインターフェイスも強調表示します。
これは次のとおりです。
public interface IRenderingArea { [JsProperty(NativeField = false)] object Model { get; set; } [JsProperty(NativeField = false)] string Result { get; } void Execute(); } public interface IRenderingArea<T>: IRenderingArea { [JsProperty(NativeField = false)] new T Model { get; set; } }
ここでは、インターフェイスには型付きおよび型なしオプションがすぐにあります。 JsPropertyを使用すると、SharpKitがResultをフィールドではなくget_Result()関数に変換することがマークされます。 したがって、cな操作のためのスペースが増えます。
基本クラス自体は次のようになります。
[JsType(JsMode.Prototype)] public abstract class HtmlArea<T>: JsContext, IRenderingArea<T> { private string _result = ""; public string Result { get { return _result; } } [JsField(Export = false)] private T _model; public T Model { get { return _model; } set { _model = value; } } [JsProperty(Export = false)] object IRenderingArea.Model { get { return Model; } set { Model = value.As<T>(); } } protected virtual void Write(object value) { if (value != null) _result += EscapeValue(value.As<JsObject>().toString()); } protected virtual string EscapeValue(JsString value) { return value .replace("&", "&") .replace("<", "<") .replace(">", ">") .replace("\"", """) .replace("'", "'"); } protected virtual void WriteLiteral(string value) { _result += value; } public abstract void Execute(); }
ご覧のとおり、このクラスはJavaScriptでの使用に適合しています。
シールドは、いくつかの特殊文字を鈍く置き換えて実行されます。
純粋に参照用として、結果のJavaScriptを引用します。
/*Generated by SharpKit v4.24.9000*/ if(typeof(XWeb) == "undefined") XWeb = {}; if(typeof(XWeb.SharpKit) == "undefined") XWeb.SharpKit = {}; if(typeof(XWeb.SharpKit.Razor) == "undefined") XWeb.SharpKit.Razor = {}; XWeb.SharpKit.Razor.AreaExtensions = function() { }; XWeb.SharpKit.Razor.AreaExtensions.Execute = function(view,model) { var area=view(); if(typeof(model) != "undefined") area.set_Model(model); area.Execute(); return area.get_Result(); }; XWeb.SharpKit.Razor.HtmlArea = function() { this._result = ""; }; XWeb.SharpKit.Razor.HtmlArea.prototype.get_Result = function() { return this._result; }; XWeb.SharpKit.Razor.HtmlArea.prototype.get_Model = function() { return this._model; }; XWeb.SharpKit.Razor.HtmlArea.prototype.set_Model = function(value) { this._model = value; }; XWeb.SharpKit.Razor.HtmlArea.prototype.Write = function(value) { if(value != null) this._result += this.EscapeValue(value.toString()); }; XWeb.SharpKit.Razor.HtmlArea.prototype.EscapeValue = function(value) { return value.replace("&","&").replace("<","<").replace(">",">").replace("\"",""").replace("'","'"); }; XWeb.SharpKit.Razor.HtmlArea.prototype.WriteLiteral = function(value) { this._result += value; };
ここで、取得した表現のクラスを実行し、それらから結果を取得できるように、何らかのメカニズムが必要です。
まず、テンプレートを実行するために必要な情報を決定する必要があります。 テンプレートを名前で参照することは可能ですが、強く型付けされたC#の世界ではどうやらコーシャではありません。 したがって、テンプレートのインスタンスを作成する方法に関する情報だけが必要であると判断しました。 つまり テンプレートを作成する機能。テンプレートに関する情報になります。 そして、テンプレートを開始するために、特別な拡張子を追加します:
[JsType(JsMode.Prototype)] public static class AreaExtensions { [JsMethod(OmitOptionalParameters = true)] public static string Execute<T>(this Func<IRenderingArea<T>> view, T model = default(T)) { var area = view(); if (JsContext.JsTypeOf(model) != JsTypes.undefined) area.Model = model; area.Execute(); return area.Result; } }
この拡張機能は、テンプレートのインスタンスを作成し、モデルをインストールし、結果を開始して取得するだけです。
クラス生成
次に、Razorエンジンが登場し、テンプレートクラスが生成されます。
ここではすべてが非常に簡単です。
痛い! Habrは書き込みを許可しなくなりました。 継続を待ちます。