The essence of my question is how to compose these objects (see below) with MVC3 and Ninject (although I'm not sure that DI should play a role in the solution). I cannot reveal the real details of my project, but here is an approximation that illustrates the problem / question. Responses to VB or C # are appreciated!
I have several different products with various properties, but all of them should be presented in the catalog. Each product class has a corresponding table in my database. There are several properties in a directory entry that are specific to entering a directory, and therefore their table. I defined an interface for directory entries with the intention that calling the DescriptionText property would give me very different results based on the underlying concrete type.
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
Given that DescriptionText is a presentation-level issue, I donβt want to implement the ICatalogEntry interface in my product classes. Instead, I want to delegate this to the format.
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
In the controller somewhere there will be such code:
Dim entries As List(Of ICatalogEntry) = catalogService.CurrentCatalog(DateTime.Now)
In the view, there will be a code somewhere:
<ul> @For Each entry As ICatalogEntry In Model.Catalog @<li>@entry.DescriptionText</li> Next </ul>
So the question is, what do designers look like? How to configure it so that the corresponding objects are created in the right places. Sounds like generics, or maybe DI can help with this, but I seem to have a mental block. The only idea I came up with is to add the ProductType property to ICatalogEntry, and then implement the factory as follows:
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
IMHO, I really don't get any smells from this code, except for having to change the factory for every new product class that comes in. However, my gut says this is an old way of doing something, and these days DI and / or generics can do it better. Suggestions on how to handle this are greatly appreciated (as are suggestions for a better name ...)