8

Pracuję w środowisku VB.Net i ostatnio zostałem poproszony o stworzenie środowiska MVC do użycia jako bazy do pracy. Postanowiłem przekonwertować najnowszą wersję SharpArchitecture (Q3 2009) na VB, która w sumie poszła dobrze po ciągnięciu za włosy. Natknąłem się na problem z Castle Windsor, w którym mój niestandardowy interfejs repozytorium (mieszkający w projekcie rdzenia/domeny), który był punktem odniesienia w konstruktorze mojego kontrolera testowego, nie został wprowadzony z konkretną implementacją (z projektu danych). Uderzyłem w mur z tego powodu, więc postanowiłem zamienić Castle Windsor na StructureMap.Problem Implementing StructureMap w VB.Net Konwersja SharpArchitecture

Wydaje mi się, że zaimplementowałem to wszystko, ponieważ wszystko kompiluje się i działa, a mój kontroler działa poprawnie, gdy odwołuje się do niestandardowego interfejsu repozytorium. Wygląda na to, że mam/lub nie mogę teraz poprawnie skonfigurować moich ogólnych interfejsów (mam nadzieję, że to ma sens, o ile jestem nowy w tym wszystkim). Kiedy używam IRepository (Of T) (chcąc, aby została wprowadzona konkretna implementacja Repository (Of Type)) w konstruktorze kontrolera, otrzymuję następujący błąd środowiska wykonawczego:

"Kod wyjątku StructureMap: 202 Brak domyślnego Wystąpienie zdefiniowane dla PluginFamily SharpArch.Core.PersistenceSupport.IRepository`1 [[DebtRemedy.Core.Page, DebtRemedy.Core, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], SharpArch.Core, Version = 1.0.0.0 , Culture = neutral, PublicKeyToken = b5f559ae0ac4e006 "

Oto fragmenty kodu, których używam (mój projekt nazywa się DebtRemedy).

Moja klasa rejestru 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 

Próbowałem zarówno ForRequestedType (co moim zdaniem jest teraz przestarzałe) oraz. IRepository (Of T) mieszka w SharpArch.Core.PersistenceSupport. Repozytorium (Of T) żyje w SharpArch.Data.NHibernate.

Moja klasa 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 

Moja controllerfactory klasa

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 

Uruchomienie rzeczy w moim global.asax

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

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

Mój kontroler testu

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 

Powyższy działa poprawnie, gdy biorę się wszystkiego zrobić z pageRepository która IRepository (Of T).

Każda pomoc w tej sprawie byłaby bardzo doceniana.

+1

Niestety, nie mogę ci pomóc z twoim problemem, ale dobrze jest zobaczyć, że są ludzie, którzy wiedzą, jak napisać dobry kod VB . Większość pytań na temat VB tutaj w Stack Overflow mnie zrozpaczała. –

+0

IMHO możesz naprawdę uprościć to pytanie - po prostu pokaż linie kodu, w których próbujesz zarejestrować typy, które się nie udają, i skonfiguruj kilka linii kodu próbujących uzyskać instancję tego typu przez fabrykę lub obiekt fabrycznie . Jeśli rejestracja nie działa, powinna zakończyć się niepowodzeniem w ten sam sposób. –

Odpowiedz

1

Wczoraj miałem podobny problem z tworzeniem instancji IRepository (Of MyEntity).

Musiałem podać y.ConnectImplementationsToTypesClosing(GetType(IRepository(Of))) w moim monitorze skanowania, aby utworzyć typową mapę StructureMap do ich implementacji.

Jak to:

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

Upewnij się, że tylko stworzenie jednego kontenera.

Również przekonwertowałem projekt C# z Castle Windsor na StructureMap. Oryginalny projekt oparty na CW stworzył kontener w Application_Start() (projekt MVC2) i przekazał go do konfiguracji. Zachowałem to samo podejście bez myślenia, trochę, kiedy tłumnie tłumaczę z hiszpańskiego na angielski, i jest tak samo złe. :)

To, co się stało, to koniec tworzenia drugiego kontenera SM. Kontener StructureMap jest statyczny, więc zawsze jest jeden "w tle". Jeśli wymyślisz kontener, faktycznie utworzysz drugi, niezależny kontener. jeśli nie jesteś ostrożny, czasami używasz jednego, czasem drugiego, i dostajesz plagę błędów "Brak domyślnej instancji" w różnych punktach, kiedy wiesz, że jest zdefiniowany ..

Sposób, w jaki go spotkałem że skończyło się zaśmiecanie mojego kodu wywołaniami WhatDoIHave(), co było szczęśliwe, ponieważ zauważyłem, że czasami widziałem skonfigurowany kontener (drugi) i czasami widziałem statyczny (pierwszy), który nie został skonfigurowany. Różne nazwy GUID stanowiły gratisów.

Sprawdź, czy to samo dzieje się w twoim kodzie VB.