c# - 具有同一接口(interface)的两个不同实例的 StructureMap Autowiring

标签 c# vb.net structuremap

这两天,我以自己的一个老项目作为具体实现的例子,努力学习了一些关于StructureMap的知识。我试图尽可能地简化我的问题。虽然我将在 vb.net 中发布我的示例,但使用 C# 示例的答案也可以。

该项目包含一个名为 IDatabase 的接口(interface),它可以将自身连接到数据库。重要部分如下所示。

Public Interface IDatabase
    Function Connect(ByVal ConnectionSettings As ConnectionSettings) As Boolean
    ReadOnly Property ConnectionOpen As Boolean
    [... more functions...]
End Interface

Public Class MSSQLConnection
    Implements IDatabase
    Public Function Connect(ByVal ConnectionSettings As ConnectionSettings) As Boolean Implements IDatabase.Connect

       [... Implementation ...]

    End Function

[... more implementations...]
End Class

ConnectionSettings 是一种结构,其中包含连接到数据库所需的所有信息。

我想打开一次数据库连接并将其用于项目中的每个连接,因此我在 ObjectFactory 中注册了一个实例。

dim foo = ObjectFactory.GetInstance(Of MSSQLConnection)()
dim bar as ConnectionSettings
foo.connect(bar)
ObjectFactory.Configure(Sub(x) x.For(Of IDatabase).Use(foo))

到这一部分为止,一切都很顺利。现在,我的一些类需要额外的 IDatabase 实例,因为它们连接到第二个数据库。

Public Class ExampleClass
Public Sub New(ByVal SameOldDatabase as IDatabase, ByVal NewDatabase as IDatabase)
[...] Magic happens here [...]
End Sub
End Class

我希望第二个 IDatabase 的行为与第一个非常相似。我希望它使用具体的单个实例,并希望将它连接到不同的数据库,使用不同的 ConnectionSettings 调用 Connect。

问题是:虽然我很确定这在某种程度上是可能的(我最初的想法是使用替代构造函数参数注册 ExampleClass),但我实际上想在不注册 ExampleClass 的情况下进行。这可能涉及更多配置,但我不知道该怎么做。

所以,基本上,归结为这个问题: 我如何配置 ObjectFactory,使 Autowiring 始终为第一个 IDatabase 参数调用带有对象 Database1 的构造函数,为第二个 IDatabase 参数调用对象 Database2(如果有的话?)

最佳答案

您可以为第二个连接使用 RegistrationConvention 和命名实例。考虑以下快速“脏”代码:

Imports StructureMap.Graph
Imports StructureMap.Configuration.DSL
Imports StructureMap

Public Module Module1

    Public Interface IDatabase
        Property ConString As String
    End Interface

    Public Class MSSQLConnection
        Implements IDatabase
        Public Property ConString() As String Implements IDatabase.ConString
    End Class

    Public Class ExampleClass
        Public Sub New(ByVal SameOldDatabase As IDatabase, ByVal NewDatabase As IDatabase)
            Console.WriteLine(SameOldDatabase.ConString)
            Console.WriteLine(NewDatabase.ConString)
        End Sub
    End Class

    Public Class SecondDatabaseConstructorIsAnotherOne
        Implements IRegistrationConvention

        Public Sub Process(ByVal type As Type, ByVal registry As Registry) Implements IRegistrationConvention.Process
            Dim ctor = type.GetConstructors().FirstOrDefault(Function(c) c.GetParameters().Where(Function(p) p.ParameterType = GetType(IDatabase)).Count = 2)
            If Not ctor Is Nothing Then

                Dim parameter = New List(Of Object)

                Dim second = False

                For Each o In ctor.GetParameters()
                    If o.ParameterType = GetType(IDatabase) AndAlso second Then
                        parameter.Add(ObjectFactory.GetNamedInstance(Of IDatabase)("secondDB"))
                    Else
                        If o.ParameterType = GetType(IDatabase) Then second = True
                        parameter.Add(ObjectFactory.GetInstance(o.ParameterType))
                    End If
                Next

                registry.For(type).Use(Function(context) Activator.CreateInstance(type, parameter.ToArray()))

            End If
        End Sub

    End Class

    Sub Main()

        Dim con1 = New MSSQLConnection() With {.ConString = "ConnectToFirstDatabase"}
        Dim con2 = New MSSQLConnection() With {.ConString = "ConnectToSecondDatabase"}

        ObjectFactory.Initialize(Sub(init)
                                     init.For(Of IDatabase).Use(con1)
                                     init.For(Of IDatabase).Add(con2).Named("secondDB")
                                 End Sub)

        ObjectFactory.Configure(Sub(config)
                                    config.Scan(Sub(scan)
                                                    scan.TheCallingAssembly()
                                                    scan.Convention(Of SecondDatabaseConstructorIsAnotherOne)()
                                                End Sub)
                                End Sub)

        ObjectFactory.GetInstance(Of ExampleClass)()
        Console.ReadLine()
    End Sub

End Module

你会明白的。

关于c# - 具有同一接口(interface)的两个不同实例的 StructureMap Autowiring ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4637235/

相关文章:

vb.net - JSON.Net - 反序列化对象格式

.net - 使用流的简单问题

c# - 如何查看一个类型是否实现了一个接口(interface)?

c# - 数组构造函数与 StructureMap 的依赖关系

wcf - 使用 WCF 的 StructureMap?

c# - StructureMap:具体类构造函数接受相同接口(interface)类型的多个参数

c# - 如何将 Webbrowser 对象转换为 AxWebbrowser?

c# - 如何使用多线程处理 C# 中的列表?

c# - 建议在 'DTO' 响应/请求中收集 REST/服务设计

c# - FTP 上传失败 'The underlying connection was closed: An unexpected error occurred on a receive.'