2011-01-09 5 views
4

В течение последних двух дней я изо всех сил пытался узнать что-то о StructureMap, используя старый проект как конкретный пример реализации. Я попытался максимально упростить мой вопрос. Хотя я буду размещать свои примеры в vb.net, ответы с примерами на C# тоже в порядке.StructureMap Autowiring с двумя разными экземплярами одного и того же интерфейса

Проект включает в себя интерфейсы, называемые IDatabase, которые соединяются с базой данных. Важная часть выглядит так.

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

До этой части все работает как шарм. Теперь я добираюсь до точки, где у меня есть классы, которым нужен дополнительный экземпляр базы данных, потому что они соединяются со второй базой данных.

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

Я хочу, чтобы эта вторая база данных вела себя так же, как и первая. Я хочу, чтобы он использовал конкретный отдельный экземпляр и хотел связать его с другой базой данных, вызывающей Connect с другими ConnectionSettings.

Проблема заключается в том, что, хотя я уверен, что это возможно, (моя первоначальная идея заключалась в регистрации ExampleClass с альтернативными аргументами конструктора), я действительно хочу сделать это без регистрации ExampleClass. Вероятно, это связано с большей конфигурацией, но я не знаю, как это сделать.

Так что, в основном, это сводится к следующему вопросу: Как настроить ObjectFactory таким образом, что автоустановка всегда вызывает конструктор с объектом Database1 для первого параметра базы данных и объекта Database2 для второго (если есть один?)

ответ

2

Вы можете использовать RegistrationConvention и именованный экземпляр для второго соединения. Рассмотрим следующий код quick'n'irty:

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 

Вы получите эту идею.

+0

Это именно то, что я хотел. Я думаю, кто-то просто должен был указать мне в сторону RegistrationConventions. Я могу продолжить свой путь оттуда. StructureMap - мощный инструмент, но в документации отсутствует что-то вроде общего направления. – Lambda