Проблема реализации StructureMap в VB.Net Преобразование SharpArchitecture - PullRequest
8 голосов
/ 27 февраля 2010

Я работаю в среде VB.Net, и недавно мне было поручено создать среду MVC для использования в качестве основы для работы. Я решил преобразовать последний выпуск SharpArchitecture (3-й квартал 2009 года) в VB, который в целом прошел хорошо после небольшого напряжения. Я столкнулся с проблемой в Castle Windsor, когда мой пользовательский интерфейс хранилища (живет в проекте core / domain), который был ссылкой в ​​конструкторе моего тестового контроллера, не внедрялся в конкретную реализацию (из проекта данных). Я ударил кирпичную стену этим, поэтому в основном решил сменить Castle Windsor на StructureMap.

Я думаю, что реализовал это нормально, так как все компилируется и работает, и мой контроллер работал нормально при обращении к пользовательскому интерфейсу репозитория. Теперь кажется, что у меня есть / или я не могу сейчас правильно настроить свои общие интерфейсы (надеюсь, это имеет смысл, поскольку я новичок во всем этом). Когда я использую IRepository (Of T) (желая внедрить его с конкретной реализацией Repository (Of Type)) в конструкторе контроллера, я получаю следующую ошибку времени выполнения:

"Код исключения StructureMap: 202 Нет экземпляра по умолчанию, определенного для PluginFamily SharpArch.Core.PersistenceSupport.IRepository`1 [[DebtRemedy.Core.Page, DebtRemedy.Core, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]], SharpArch.Core, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = b5f559ae0ac4e006 "

Вот мои выдержки из кода, которые я использую (мой проект называется DebtRemedy).

Мой класс реестра структуры структуры

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.

Мой сервисный локатор класса

    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

Мой контроллерзавод класса

    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).

Любая помощь с этим будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 21 августа 2010

Убедитесь, что вы создаете только один контейнер.

Я также преобразовал проект C # из Castle Windsor в StructureMap.Исходный CW-проект создал экземпляр Container в Application_Start () (проект MVC2) и передал его для настройки.Я придерживался того же подхода, не задумываясь, вроде когда вы переводите с испанского на английский буквально, и это так же плохо.:)

В результате я создал второй контейнер SM.Контейнер StructureMap является статическим, и поэтому всегда есть один «в фоновом режиме».Если вы создаете новый контейнер, вы фактически создаете второй независимый контейнер.если вы неосторожны, вы в конечном итоге иногда используете одну, иногда другую, и получаете чуму ошибок «No Default Instance» в разные моменты, когда вы знаете, что она определена ..

То, как я столкнулсяэто то, что я закончил засорять свой код вызовами WhatDoIHave (), что повезло, потому что я заметил, что иногда я видел настроенный контейнер (второй), а иногда я видел статический (первый), который не был настроен.Различными именами GUID была дешевая распродажа.

Проверьте, происходит ли то же самое в вашем коде VB.

1 голос
/ 12 августа 2010

У меня вчера была похожая проблема с созданием экземпляра IRepository (Of 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
0 голосов
/ 28 августа 2010

Не очень знаком с этим, но похоже, что он не может быть зарегистрирован в контейнере или потому что распознаватель жадный, он может выбрать конструктор, который не имеет зарегистрированных элементов. Следующий URL выглядит очень похоже на ту же проблему, посмотрите ... http://learningbyfailing.com/2010/02/structuremap-exception-no-default-instance-defined-for-pluginfamily-iformsauthentication/

...