Проблема с реализацией StructureMap в VB.Net Преобразование SharpArchitecture
-
23-09-2019 - |
Вопрос
Я работаю в среде VB.Net, и недавно мне было поручено создать среду MVC для использования в качестве основы для работы.Я решил преобразовать последнюю версию SharpArchitecture (3 квартал 2009) в VB, которая в целом прошла нормально после небольшого выдергивания волос.Я столкнулся с проблемой с Castle Windsor, где мой пользовательский интерфейс репозитория (находится в проекте core / domain), который был ссылкой в конструкторе моего тестового контроллера, не был внедрен в конкретную реализацию (из проекта data).Я наткнулся на кирпичную стену с этим, поэтому в основном решил заменить Castle Windsor на StructureMap.
Я думаю, что я реализовал это нормально, поскольку все компилируется и запускается, и мой контроллер работал нормально при обращении к пользовательскому интерфейсу репозитория.Теперь кажется, что я правильно настроил / или не могу настроить свои универсальные интерфейсы (я надеюсь, что это имеет смысл, поскольку я новичок во всем этом).Когда я использую IRepository (Of T) (желая, чтобы он был введен с конкретной реализацией репозитория (Типа)) в конструкторе контроллера, я получаю следующую ошибку времени выполнения:
"Код исключения StructureMap:202 Для плагина SharpArch.Core.PersistenceSupport не определен экземпляр по умолчанию.IRepository`1[[DebtRemedy.Core.Page, DebtRemedy.Ядро, версия=1.0.0.0, Культура = нейтральная, PublicKeyToken=null]], SharpArch.Ядро, версия=1.0.0.0, Культура = нейтральная, PublicKeyToken=b5f559ae0ac4e006"
Вот выдержки из моего кода, которые я использую (мой проект называется DebtRemedy).
Мой класс реестра 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
Я пробовал как ForRequestedType (который, я думаю, теперь устарел), так и For.IRepository(Of T) живет в SharpArch.Core.PersistenceSupport.Хранилище (Of T) находится в SharpArch.Data.NHibernate.
Мой класс 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
Мой класс 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
Материал для инициализации в моем global.asax
Dim container As IContainer = New Container(New DefaultRegistry)
ControllerBuilder.Current.SetControllerFactory(New ServiceLocatorControllerFactory())
ServiceLocator.SetLocatorProvider(Function() New StructureMapServiceLocator(container))
Мой тестовый контроллер
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
Описанное выше работает нормально, когда я удаляю все, что связано с pageRepository, который является IRepository (Of T).
Мы были бы очень признательны за любую помощь в этом.
Нет правильного решения
Другие советы
Вчера у меня была аналогичная проблема с созданием экземпляра IRepository (Из MyEntity).
Я должен был заявить y.ConnectImplementationsToTypesClosing(GetType(IRepository(Of )))
в моем Scan делегируйте, чтобы сделать StructureMap сопоставление универсальных типов с их реализацией.
Вот так:
Private Shared Sub SetupCustomRepositories(ByVal y As IAssemblyScanner)
y.Assembly("DebtRemedy.Core")
y.Assembly("DebtRemedy.Data")
y.WithDefaultConventions()
y.ConnectImplementationsToTypesClosing(GetType(Of ));
End Sub
Убедитесь, что вы создаете только один контейнер.
Я также преобразовал проект C # из Castle Windsor в StructureMap.Исходный проект на основе CW создал экземпляр контейнера в Application_Start() (проект MVC2) и передал его для настройки.Я, не задумываясь, придерживался того же подхода, что и при буквальном переводе с испанского на английский, и это так же плохо.:)
Что произошло, так это то, что в итоге я создал второй контейнер SM.Контейнер StructureMap статичен, и поэтому он всегда есть "в фоновом режиме".Если вы создаете новый контейнер, вы фактически создаете второй, независимый контейнер.если вы не будете осторожны, вы в конечном итоге иногда используете одно, иногда другое и получаете множество ошибок "Нет экземпляра по умолчанию" в разные моменты, когда вы знаете, что это определено..
Я столкнулся с этим так, что в итоге засорил свой код вызовами WhatDoIHave(), что было удачно, потому что я заметил, что иногда я видел настроенный контейнер (второй), а иногда я видел статический контейнер (первый), который не был настроен.Разные имена GUID были розыгрышем призов.
Проверьте, происходит ли то же самое в вашем коде VB.
Не очень знаком с этим, но похоже, что он может не быть зарегистрирован в контейнере или из-за того, что распознаватель жадный, он может выбрать конструктор, в котором нет зарегистрированных элементов.Следующий URL-адрес выглядит очень похоже на ту же проблему, взгляните...http://learningbyfailing.com/2010/02/structuremap-exception-no-default-instance-defined-for-pluginfamily-iformsauthentication/