StructureMap Autowiring with two different instances of the same interface

Over the past two days, I have been struggling to learn something about StructureMap, using the old project as a concrete implementation example. I tried to simplify my question as much as possible. Although I will post my examples on vb.net, the answers with examples in C # are also in order.

The project includes interfaces called IDatabase, which connect to the database. The important part looks like this.

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 is a structure that has all the information needed to connect to a database.

I want to open a database connection once and use it for each individual connection in the project, so I am registering an instance in ObjectFactory.

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

Until this part, everything works like a charm. Now I get to the point where I have classes that need an extra database instance because they connect to the second database.

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

I want this second database to behave the same as the first. I want it to use a specific single instance and would like to connect it to another database calling Connect with other ConnectionSettings.

The problem is that although I am pretty sure that this is possible (my initial idea was to register ExampleClass with alternative constructor arguments), I really want to do this without registering ExampleClass. This is probably due to the larger configuration, but I have no idea how to do this.

So, basically, it comes down to this question: How to configure ObjectFactory in such a way that auto-installation always calls a constructor with a Database1 object for the first database parameter and a Database2 object for the second (if there is one?)

+4
source share
1 answer

You can use RegistrationConvention and a named instance for the second connection. Consider the following quick'n'dirty code:

 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 

You will get this idea.

+2
source

Source: https://habr.com/ru/post/1334792/


All Articles