8

Lavoro in un ambiente VB.Net e recentemente mi è stato assegnato il compito di creare un ambiente MVC da utilizzare come base da cui lavorare. Ho deciso di convertire l'ultima versione di SharpArchitecture (Q3 2009) in VB, che nel complesso è andata bene dopo aver tirato un po 'di capelli. Mi sono imbattuto in un problema con Castle Windsor, in cui la mia interfaccia di repository personalizzata (che vive nel progetto core/dominio) di riferimento nel costruttore del mio controller di test non è stata iniettata con l'implementazione concreta (dal progetto di dati). Ho colpito un muro di mattoni con questo in modo sostanzialmente deciso di cambiare Castle Windsor per StructureMap.Problema Implementazione di StructureMap nella conversione VB.Net di SharpArchitecture

Penso di aver implementato questo ok in quanto tutto compila ed esegue e il mio controller ha funzionato bene quando fa riferimento a un'interfaccia repository personalizzata. Ora sembra che ho/o non posso ora configurare correttamente le mie interfacce generiche (spero che questo abbia senso per quanto io sia nuovo a tutto questo). Quando utilizzo IRepository (Of T) (volendo che venga iniettato con un'implementazione concreta di Repository (Of Type)) nel costruttore controller ricevo il seguente errore di runtime:

"StructureMap Codice eccezione: 202 No Default Istanza definita per PluginFamily SharpArch.Core.PersistenceSupport.IRepository`1 [[DebtRemedy.Core.Page, DebtRemedy.Core, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], SharpArch.Core, Versione = 1.0.0.0 , Culture = neutro, PublicKeyToken = b5f559ae0ac4e006 "

Ecco i miei estratti di codice che sto utilizzando (il mio progetto si chiama DebtRemedy).

La mia classe registro StructureMap

Public Class DefaultRegistry 
    Inherits Registry 

    Public Sub New() 
     ''//Generic Repositories 
     AddGenericRepositories() 
     ''//Custom Repositories 
     AddCustomRepositories() 
     ''//Application Services 
     AddApplicationServices() 
     ''//Validator 
     [For](GetType(IValidator)).Use(GetType(Validator)) 
    End Sub 

    Private Sub AddGenericRepositories() 
     ''//ForRequestedType(GetType(IRepository(Of))).TheDefaultIsConcreteType(GetType(Repository(Of))) 
     [For](GetType(IEntityDuplicateChecker)).Use(GetType(EntityDuplicateChecker)) 
     [For](GetType(IRepository(Of))).Use(GetType(Repository(Of))) 
     [For](GetType(INHibernateRepository(Of))).Use(GetType(NHibernateRepository(Of))) 
     [For](GetType(IRepositoryWithTypedId(Of ,))).Use(GetType(RepositoryWithTypedId(Of ,))) 
     [For](GetType(INHibernateRepositoryWithTypedId(Of ,))).Use(GetType(NHibernateRepositoryWithTypedId(Of ,))) 
    End Sub 

    Private Sub AddCustomRepositories() 
     Scan(AddressOf SetupCustomRepositories) 
    End Sub 

    Private Shared Sub SetupCustomRepositories(ByVal y As IAssemblyScanner) 
     y.Assembly("DebtRemedy.Core") 
     y.Assembly("DebtRemedy.Data") 
     y.WithDefaultConventions() 
    End Sub 

    Private Sub AddApplicationServices() 
     Scan(AddressOf SetupApplicationServices) 
    End Sub 

    Private Shared Sub SetupApplicationServices(ByVal y As IAssemblyScanner) 
     y.Assembly("DebtRemedy.ApplicationServices") 
     y.With(New FirstInterfaceConvention) 
    End Sub 

End Class 

Public Class FirstInterfaceConvention 
    Implements ITypeScanner 

    Public Sub Process(ByVal type As Type, ByVal graph As PluginGraph) Implements ITypeScanner.Process 
     If Not IsConcrete(type) Then 
      Exit Sub 
     End If 
     ''//only works on concrete types 
     Dim firstinterface = type.GetInterfaces().FirstOrDefault() 
     ''//grabs first interface 
     If firstinterface IsNot Nothing Then 
      graph.AddType(firstinterface, type) 
     Else 
      ''//registers type 
      ''//adds concrete types with no interfaces 
      graph.AddType(type) 
     End If 
    End Sub 
End Class 

Ho provato sia ForRequestedType (che credo sia ora sconsigliato) E PER. L'IRepository (Of T) vive in SharpArch.Core.PersistenceSupport. Il repository (Of T) vive in SharpArch.Data.NHibernate.

La mia classe ServiceLocator

Public Class StructureMapServiceLocator 
    Inherits ServiceLocatorImplBase 
    Private container As IContainer 

    Public Sub New(ByVal container As IContainer) 
     Me.container = container 
    End Sub 

    Protected Overloads Overrides Function DoGetInstance(ByVal serviceType As Type, ByVal key As String) As Object 
     Return If(String.IsNullOrEmpty(key), container.GetInstance(serviceType), container.GetInstance(serviceType, key)) 
    End Function 

    Protected Overloads Overrides Function DoGetAllInstances(ByVal serviceType As Type) As IEnumerable(Of Object) 
     Dim objList As New List(Of Object) 
     For Each obj As Object In container.GetAllInstances(serviceType) 
      objList.Add(obj) 
     Next 
     Return objList 
    End Function 
End Class 

La mia classe ControllerFactory

Public Class ServiceLocatorControllerFactory 
    Inherits DefaultControllerFactory 

    Protected Overloads Overrides Function GetControllerInstance(ByVal requestContext As RequestContext, ByVal controllerType As Type) As IController 
     If controllerType Is Nothing Then 
      Return Nothing 
     End If 

     Try 
      Return TryCast(ObjectFactory.GetInstance(controllerType), Controller) 
     Catch generatedExceptionName As StructureMapException 
      System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave()) 
      Throw 
     End Try 
    End Function 

End Class 

La roba inizializzazione nel mio global.asax

Dim container As IContainer = New Container(New DefaultRegistry) 
ControllerBuilder.Current.SetControllerFactory(New ServiceLocatorControllerFactory()) 

ServiceLocator.SetLocatorProvider(Function() New StructureMapServiceLocator(container)) 

mio controller di test

Public Class DataCaptureController 
Inherits BaseController 

Private ReadOnly clientRepository As IClientRepository() 
Private ReadOnly pageRepository As IRepository(Of Page) 

Public Sub New(ByVal clientRepository As IClientRepository(), ByVal pageRepository As IRepository(Of Page)) 
    Check.Require(clientRepository IsNot Nothing, "clientRepository may not be null") 
    Check.Require(pageRepository IsNot Nothing, "pageRepository may not be null") 
    Me.clientRepository = clientRepository 
    Me.pageRepository = pageRepository 
End Sub 

Function Index() As ActionResult 
    Return View() 
End Function 

È possibile che questo funziona bene quando prendo tutto ciò a che fare con la pageRepository che è IRepository (Of T).

Qualsiasi aiuto con questo sarebbe molto apprezzato.

+1

Purtroppo non posso aiutarti con il tuo problema ma è bello vedere che ci sono persone là fuori che sanno scrivere un buon codice VB . La maggior parte delle domande VB qui su Stack Overflow mi ha fatto disperare. –

+0

IMHO si potrebbe davvero semplificare questa domanda - basta mostrare le linee di codice in cui si sta tentando di registrare i tipi che stanno fallendo, e impostare poche righe di codice cercando di ottenere un'istanza di quel tipo attraverso il contenitore o la fabbrica di oggetti . Se la registrazione non funziona, dovrebbe fallire allo stesso modo. –

risposta

1

Ho avuto un problema simile ieri con l'istanziazione di IRepository (Of MyEntity).

Ho dovuto dichiarare y.ConnectImplementationsToTypesClosing(GetType(IRepository(Of))) nel mio delegato di scansione per rendere StructureMap mappare i tipi generici alla loro implementazione.

Ti piace questa:

Private Shared Sub SetupCustomRepositories(ByVal y As IAssemblyScanner) 
    y.Assembly("DebtRemedy.Core") 
    y.Assembly("DebtRemedy.Data") 
    y.WithDefaultConventions() 
    y.ConnectImplementationsToTypesClosing(GetType(Of)); 
End Sub 
1

Assicurarsi che si sta creando un unico contenitore.

Ho anche convertito un progetto C# da Castle Windsor a StructureMap. Il progetto originale basato su CW ha istanziato un contenitore in Application_Start() (progetto MVC2) e lo ha passato in giro per la configurazione. Ho mantenuto lo stesso approccio senza pensare, un pò quando traduci da spagnolo a inglese letteralmente, ed è altrettanto brutto. :)

Quello che è successo è che ho finito per creare un secondo contenitore SM. Il contenitore di StructureMap è statico e quindi c'è sempre uno "in background". Se si crea un nuovo contenitore, si crea effettivamente un secondo contenitore indipendente. se non stai attento, a volte ne usi uno, a volte l'altro, e ricevi una piaga degli errori "Nessuna istanza predefinita" in vari punti quando sai che è definito.

Il modo in cui mi sono imbattuto è che ho finito per sporcare il mio codice con le chiamate WhatDoIHave(), il che è stato positivo perché ho notato che a volte ho visto un contenitore configurato (il secondo) e talvolta ho visto quello statico (il primo), che non era stato configurato. I diversi nomi GUID erano il regalo.

Verificare se lo stesso sta accadendo nel codice VB.

Problemi correlati