私の質問の本質は、MVC3 と Ninject を使用してこれらのオブジェクト (以下を参照) を賢明な方法で構成する方法です (ただし、DI がソリューションで役割を果たすべきかどうかはわかりません)。私のプロジェクトの実際の詳細を開示することはできませんが、問題/質問を説明する近似値を次に示します。VB または C# での回答を歓迎します。
さまざまな特性を持ついくつかの異なる製品がありますが、それらすべてをカタログに表示する必要があります。データベースには、各製品クラスに対応するテーブルがあります。カタログ エントリには、カタログ エントリであることに固有のいくつかのプロパティがあり、その結果、独自のテーブルがあります。DescriptionText プロパティを呼び出すと、基になる具象型に基づいて非常に異なる結果が得られるという意図で、カタログ エントリのインターフェイスを定義しました。
Public Class Clothing
Property Identity as Int64
Property AvailableSizes As List(Of String)
Property AvailableColor As List(Of String)
End Class
Public Class Fasteners
Property Identity as Int64
Property AvailableSizes As List(Of String)
Property AvailableFinishes As List(Of String)
Property IsMetric As Boolean
End Class
Public Interface ICatalogEntry
Property ProductId as Int64
Property PublishedOn As DateTime
Property DescriptionText As String
End Interface
DescriptionText がプレゼンテーション層の問題であることを考えると、製品クラスに ICatalogEntry インターフェイスを実装したくありません。代わりに、それをある種のフォーマッターに委任したいと思います。
Public Interface ICatalogEntryFormatter
Property DescriptionText As String
End Interface
Public Class ClothingCatalogEntryFormatter
Implements ICatalogEntryFormatter
Property DescriptionText As String
End Class
Public Class FastenerCatalogEntryFormatter
Implements ICatalogEntryFormatter
Property DescriptionText As String
End Class
コントローラーのどこかに、次のようなコードがあります。
Dim entries As List(Of ICatalogEntry)
= catalogService.CurrentCatalog(DateTime.Now)
どこかのビューには、次のようなコードがあります。
<ul>
@For Each entry As ICatalogEntry In Model.Catalog
@<li>@entry.DescriptionText</li>
Next
</ul>
問題は、コンストラクターがどのように見えるかということです。適切なオブジェクトが適切な場所でインスタンス化されるように設定する方法。ジェネリックまたは DI がこれを助けることができるようですが、私は精神的なブロックを抱えているようです. 私が思いついた唯一のアイデアは、ProductType プロパティを ICatalogEntry に追加し、次のようなファクトリを実装することです。
Public Class CatalogEntryFactory
Public Function Create(catEntry as ICatalogEntry) As ICatalogEntry
Select Case catEntry.ProductType
Case "Clothing"
Dim clothingProduct = clothingService.Get(catEntry.ProductId)
Dim clothingEntry = New ClothingCatalogEntry(clothingProduct)
Return result
Case "Fastener"
Dim fastenerProduct = fastenerService.Get(catEntry.ProductId)
Dim fastenerEntry = New FastenerCatalogEntry(fastenerProduct)
fastenerEntry.Formatter = New FastenerCatalogEntryFormatter
Return fastenerEntry
...
End Function
End Class
Public ClothingCatalogEntry
Public Sub New (product As ClothingProduct)
Me.Formatter = New ClothingCatalogEntryFormatter(product)
End Sub
Property DescriptionText As String
Get
Return Me.Formatter.DescriptionText
End Get
End Property
End Class
...FastenerCatalogEntry is omitted but you get the idea...
Public Class CatalogService
Public Function CurrentCatalog(currentDate as DateTime)
Dim theCatalog As List(Of ICatalogEntry)
= Me.repository.GetCatalog(currentDate)
Dim theResult As New List(Of ICatalogEntry)
For Each entry As ICataLogEntry In theCatalog
theResult.Add(factory.Create(entry))
Next
Return theResult
End Function
End Class
私見ですが、新しい製品クラスが登場するたびにファクトリを変更する必要があることを除けば、このコードから臭いを感じることはありません。それでも、私の直感では、これは古い方法であり、最近では DI やジェネリックがこれをより適切に行うことができると言っています。これを処理する方法に関する提案は大歓迎です (より良いタイトルに関する提案も同様です...)