Die Essenz meiner Frage ist, wie diese Objekte (siehe unten) in sinnvoller Weise mit MVC3 und Ninject zusammengesetzt werden (obwohl ich nicht sicher bin, sollte DI eine Rolle in der Lösung spielen). Ich kann die wahren Details meines Projekts nicht offen legen, aber hier ist eine Annäherung, die das Thema/die Frage veranschaulicht. Antworten in VB oder C# sind willkommen!Komponieren von polymorphen Objekten in ASP.NET MVC3 Projekt
Ich habe mehrere verschiedene Produkte mit sehr unterschiedlichen Eigenschaften, aber alle müssen in einem Katalog vertreten sein. Jede Produktklasse hat eine entsprechende Tabelle in meiner Datenbank. Ein Katalogeintrag hat eine Handvoll Eigenschaften, die spezifisch für einen Katalogeintrag sind und folglich eine eigene Tabelle haben. Ich habe eine Schnittstelle für die Katalogeinträge mit der Absicht definiert, dass das Aufrufen der DescriptionText -Eigenschaft sehr unterschiedliche Ergebnisse basierend auf dem zugrundeliegenden konkreten Typ gibt.
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
Da die Description ein Anliegen Präsentationsschicht ist, ich will nicht die ICatalogEntry Schnittstelle in meinen Produktklassen implementieren. Stattdessen möchte ich das an eine Art Formatierer delegieren.
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 einem Controller irgendwo wird es Code wie folgt sein:
Dim entries As List(Of ICatalogEntry)
= catalogService.CurrentCatalog(DateTime.Now)
In einer Ansicht irgendwo wird es Code wie folgt sein:
<ul>
@For Each entry As ICatalogEntry In Model.Catalog
@<li>@entry.DescriptionText</li>
Next
</ul>
Die Frage ist also, was die tun Konstruktoren sehen aus? Wie es eingerichtet wird, damit die entsprechenden Objekte an den richtigen Stellen instanziiert werden. Scheint wie Generika oder vielleicht DI kann dabei helfen, aber ich habe eine mentale Blockade. Die einzige Idee, die ich habe kommen mit ist eine Product Eigenschaft ICatalogEntry hinzufügen und dann eine Fabrik wie folgt implementieren:
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, ich bin nicht wirklich immer riecht aus diesen Code anders als mit der sich ändern Fabrik für jede neue Produktklasse, die mitkommt. Aber mein Bauchgefühl sagt, dass dies die alte Art ist, Dinge zu tun, und heutzutage können DI und/oder Generika das besser machen. Vorschläge, wie man damit umgeht, werden sehr geschätzt (ebenso wie Vorschläge zu einem besseren Titel ...)
So behandelt der benutzerdefinierte Resolver die Tatsache, dass mehr als eine Klasse der gleichen Schnittstelle zugeordnet ist? Das ist es, was mich in meiner Frage in die Fabrikklasse treibt, und das ist es, was mir am unbehaglichsten und völlig unklar ist, wie ich mich loswerden kann. – schmidlop
Ok, jetzt, da ich den von Ihnen bereitgestellten Link gelesen habe, bin ich zu dem Schluss gekommen, dass ich vernünftigerweise erwarten sollte, dass mein DI-Container (Ninject) eine Antwort für dieses Szenario hat. Außerdem sieht es so aus und ich brauche eine kontextuelle Bindung https://github.com/ninject/ninject/wiki/Contextual-Binding und ich brauche das wahrscheinlich auch: https://github.com/ninject/ninject.extensions. factory/wiki – schmidlop
Ja, das sollte eigentlich dein Problem lösen. In Ihrer Ninject-Initialisierung sollten Sie in der Lage sein, aus einer Ressourcendatei zu laden. –