Asp.Net Mvcの研究とlugstore.infoの開発の過程で生まれた
まず、問題/目標を定式化します。
マスターページに1つのViewModel(htmlタイトル、アクセス可能なメニューなど)が必要な場合、ページに別の例(逸話のリストなど)が必要な場合、ページレットの場合は通常3番目(タグのリスト)になります。 さらに、同じページレットを他のページに簡単に移植できるようにするかゆみ。
さて、理解し始めましょう:
- 型指定の強いビュー:小さいページに適したオプション。 ただし、上記のように、複数のネストされたマスターページを使用し、それぞれに独自のモデルがある場合、継承、ネストによりひどくなり始める可能性があり、クラスと依存関係の図はハブのロゴに似たものになります。 私見そのような混乱-Feh ...あなたは彼らのインターフェースを共有しようとすることができます。 もちろん、彼らが適切なアーキテクチャソリューションを思いついた可能性はありますが、それは残念ですが、私はそれらに会っていないか、共有していません。
- ViewData [string key]:普遍的で、レンダリングに関係するすべてのビューからアクセスできますが、string-keyによる検索と入力の欠如により、このメソッドは非常に悲しく、潜在的にバグがあります。 ただし、魚なしで行うことも可能です。
- 独自のオプション:見つかったメソッドが機能しなかったため、私はこの方法で行った。 そして、私はそれを後悔していません。
思考の飛行:
各ViewModelは個別に何ですか? お茶をすすりながら思った。 答えはそれ自体で熟成しました: 可能であればロジックなしの型付きデータのコンテナー (HtmlHelper拡張メソッドでのロジックのレンダリングも好きです)。
既存のツールを使用して複数のモデルをコントローラーからビューに転送する方法は? -飲み物のもう一口、 -mm、同じViewDataがありますが、最初はそれを拒否しました。
コンパイル時に型チェックを行い、文字列キー検索を取り除く方法は? -救助に汎用的! -クッキーを噛みます。
実装を追加する方法ですが、使用するために何かを継承する必要はありませんか? -Taki拡張。
...
利益:
実際、次の2つの方法があります。
- ViewDataのキー生成:
public static String GetKey < TModel > ( )
{
typeof ( TModel )を 返します。 氏名
}
- デフォルト値を使用してモデルまたはその作成を検索します。
public static TModel Model < TModel > ( この ViewDataDictionary viewData )
{
String key = GetKey < TModel > ( ) ;
if ( viewData。ContainsKey ( key ) )
{
オブジェクトモデル= viewData [キー] ;
if ( ( model != null ) && ( model。GetType ( ) 。 Equals ( typeof ( TModel ) ) ) ))
{
return ( TModel )モデル;
}
}
TModel newModel =アクティベーター。 CreateInstance < TModel > ( ) ;
viewData [キー] = newModel ;
newModelを返します。
}
public static TModel Model < TModel > ( このコントローラーコントローラー)
{
コントローラーを返します。 ViewData 。 モデル < TModel > ( ) ;
}
public static TModel Model < TModel > ( この HtmlHelper htmlHelper )
{
htmlHelperを返します。 ViewData 。 モデル < TModel > ( ) ;
}
プラスとして、あなたは強調することができます:
- 複数の独立したモデルを描画するために、コンテナでそれらを結合する必要はありません。 おそらく最も便利です。
- 各小さなモデルは、それ自体と、それをレンダリングするページについてのみ知っています。 転送するのが便利で、コントローラーのデータは(そのままの状態で)埋められます。 ページでの特定のアクションの弱さ。 その結果、任意のモデルを任意のページに描画できます。
- モデルオブジェクトは、最初の呼び出し(コントローラーまたはビューから)で作成されます。nullをチェックする必要はありません。必ずViewDataにあることを確認してください。 どこかに記入するのを忘れると、デフォルト値になります。
- StrongTypedビューを実行する必要はありません(ほとんどありません;)。
- モデルには、Activatorが作成できるようにパブリックコンストラクターが必要です。 (これは疑わしいマイナス点です。実際、キャッシングアクティベーターコンストラクターは、元の式の4倍高速な式を使用して作成されました);
- 構文は少し複雑です。
使用法:
コントローラー内:
Public ActionResultデフォルト( )
{
...
//ページレットでレンダリング
これ 。 モデル < TagListViewModel > ( ) 。 MyBlaBlaBlaProperty = " lolstore.info " ;
//アクションの現在のマスターページで使用
これ 。 モデル < UserMenuViewModel > ( ) 。 MyBlaBlaBlaProperty2 = "ジョーク" ;
}
強い型の継承のないビュー:
<% = this 。 モデル < TagListViewModel > ( ) 。 MyBlaBlaBlaProperty %>
HtmlHelperの場合:
public static MvcHtmlString RenderSomething ( この HtmlHelper htmlHelper )
{
if ( ! htmlHelper。ModelExists < TagListViewModel > ( ) )
{
return new MvcHtmlString ( String。Empty ) ;
}
TagListViewModelモデル= htmlHelper。 モデル < TagListViewModel > ( ) ;
//どのスレッドをレンダリングする
}
コードファイル全体は、 ここからダウンロードできます 。
Z.Y. このような実験が居住者にとって興味深いものであり、私のプロジェクトだけでなく適用できる場合は、競合および非同期キャッシングの実装、単純なAutoMapper(継承、インターフェース、コンパイル段階での検証なしで、あるタイプのオブジェクトを別のタイプにクローンするために使用)およびその他の有用性をレイアウトします。
によってEugeneOstapchuk