문제

I work in a VB.Net environment and have recently been tasked with creating an MVC environment to use as a base to work from. I decided to convert the latest SharpArchitecture release (Q3 2009) into VB, which on the whole has gone fine after a bit of hair pulling. I came across a problem with Castle Windsor where my custom repository interface (lives in the core/domain project) that was reference in the constructor of my test controller was not getting injected with the concrete implementation (from the data project). I hit a brick wall with this so basically decided to switch out Castle Windsor for StructureMap.

I think I have implemented this ok as everything compiles and runs and my controller ran ok when referencing a custom repository interface. It appears now that I have/or cannot now setup my generic interfaces up properly (I hope this makes sense so far as I am new to all this). When I use IRepository(Of T) (wanting it to be injected with a concrete implementation of Repository(Of Type)) in the controller constructor I am getting the following runtime error:

"StructureMap Exception Code: 202 No Default Instance defined for 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"

Here are my code excerpts that I am using (my project is called DebtRemedy).

My structuremap registry class

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

I have tried both ForRequestedType (which I think is now deprecated) and For. IRepository(Of T) lives in SharpArch.Core.PersistenceSupport. Repository(Of T) lives in SharpArch.Data.NHibernate.

My servicelocator class

    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

My controllerfactory 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

The initialise stuff in my global.asax

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

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

My test controller

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

The above works fine when I take out everything to do with the pageRepository which is IRepository(Of T).

Any help with this would be greatly appreciated.

올바른 솔루션이 없습니다

다른 팁

I had a similar issue yesterday with instantiating IRepository(Of MyEntity).

I had to state y.ConnectImplementationsToTypesClosing(GetType(IRepository(Of ))) in my Scan delegate to make StructureMap map generic types to their implementation.

Like this:

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. 목록으로 이동 한 다음 필요한 이름으로 목록에 새 열을 만듭니다.

  2. "계산"할 열의 유형을 선택하십시오.

  3. 공식 "섹션에서"생성 된 "열을 선택하십시오.

  4. DataType 리턴을 선택합니다.

  5. "확인"을 클릭하십시오.

    아래 코드를 사용하여 계산 된 열을 프로그래밍 방식으로 추가하십시오.

      using (SPSite site = new SPSite("http://serverName/sites/Vijai/"))        
            {           
             using (SPWeb web = site.OpenWeb())    
                    {    
                        SPList list = web.Lists.TryGetList("Custom");        
                    if (list != null)         
                   {            
                    ////Create a calculated field  
                       string calculatedColumn = list.Fields.Add("CalculatedColumn",SPFieldType.Calculated, false);                      
          ////Get the newly created calculated field         
                       SPFieldCalculated calculatedField = list.Fields[calculatedColumn] as SPFieldCalculated;    
    
                         ////Set the calculated field formula 
    
                               calculatedField.Formula = "=[Title]";  
                              ////Set the data type returned from this formula  
                              calculatedField.OutputType = SPFieldType.Text;                       
     ////Update the calculated field  
                    calculatedField.Update();        
                }          
          }          
      }
    
    .

    아래 코드를 사용하여 element.xml 를 사용하여 열을 추가하십시오.

    <Field   Type="Calculated"   DisplayName="Name"  
    EnforceUniqueValues="FALSE"   Indexed="FALSE"  
    Format="Requiredformat"   LCID="1033"   ResultType="Text"  
    ReadOnly="TRUE"   ID="{85353f64-8c8f-4424-ba81-bdc07b9880d6}"  
    SourceID="{b9c7c8c2-7106-4219-84f9-b3d7cd0a9760}"   StaticName="Name" 
    Name="Name"   ColName="Name"   RowOrdinal="0"   Required="FALSE"  
    Percentage="FALSE"   Version="3"> 
    <Formula>=[Created]</Formula></Field>
    
    .

Not that familiar with this, but it looks like it may not be registered with the container or because the resolver is greedy it might choose a constructor that does not have registered items. The following URL looks very similar to the same problem take a look... http://learningbyfailing.com/2010/02/structuremap-exception-no-default-instance-defined-for-pluginfamily-iformsauthentication/

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top