这两天,我以自己的一个老项目作为具体实现的例子,努力学习了一些关于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/