VB.NETでもAutofacで依存性を注入したい

はじめに

OpenCoverのコードを読んでいたら、AutofacというDIライブラリが使用されており、気になったのでそれについてです。

チュートリアル

Getting Started — Autofac 4.0 documentation

大体の手順をざっくりと列挙すると

  1. 脳内でいい感じに制御の反転を組み立てる
  2. Autofacの参照を追加する
  3. アプリケーションの開始時に
  4. ContainerBuilderインスタンスを生成し
  5. コンポーネントを登録して
  6. コンテナを生成して
  7. アプリケーションの実行の間
  8. ライフタイムスコープを生成して
  9. ライフタイムスコープを使ってコンポーネントインスタンスを解決する

といった感じです。

Imports Autofac

Module Module1
    Sub Main()
        Dim builder = New ContainerBuilder()
        builder.RegisterType(Of ConsoleOutput)().As(Of IOutput)()

        Dim container = builder.Build()

        Using scope = container.BeginLifetimeScope()
            Dim out = scope.Resolve(Of IOutput)()
            out.WriteLine("hello world")
        End Using
    End Sub
End Module

Interface IOutput
    Sub WriteLine(value As String)
End Interface

Class ConsoleOutput
    Implements IOutput, IDisposable

    Public Sub WriteLine(value As String) Implements IOutput.WriteLine
        Console.WriteLine(value)
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Console.WriteLine("IDisposable.Dispose")
    End Sub
End Class
hello world
IDisposable.Dispose

直接コンテナからコンポーネントインスタンスを生成せずに、ライフタイムスコープからインスタンスを生成することでライフタイムスコープが破棄された時点でライフタイムスコープから生成されたインスタンスも同時に破棄されます。

また、コンポーネントに複数のコンストラクタが存在する場合、コンテナ内に引数となりうる他のコンポーネントが登録されていればそのコンストラクタを使用してインスタンスを生成してくれます。

Module Module1

    Sub Main()
        With "ジャムおじさんとバタコ"
            Dim builder = New ContainerBuilder()
            builder.RegisterType(Of AnpanMan)().As(Of IAnpanMan)()
            builder.RegisterType(Of Jam)().As(Of IJam)()
            builder.RegisterType(Of Batako)().As(Of IBatako)()
            Dim container = builder.Build()

            Using scope = container.BeginLifetimeScope()
                scope.Resolve(Of IAnpanMan)().Anpanchi()
            End Using
        End With

        With "バタコのみ"
            Dim builder = New ContainerBuilder()
            builder.RegisterType(Of AnpanMan)().As(Of IAnpanMan)()
            builder.RegisterType(Of Batako)().As(Of IBatako)()
            Dim container = builder.Build()

            Using scope = container.BeginLifetimeScope()
                scope.Resolve(Of IAnpanMan)().Anpanchi()
            End Using
        End With
    End Sub

End Module

Interface IBatako
End Interface

Class Batako
    Implements IBatako
End Class

Interface IJam
End Interface

Class Jam
    Implements IJam
End Class

Interface IAnpanMan
    Sub Anpanchi()
End Interface

Class AnpanMan
    Implements IAnpanMan

    Private _anpanchi As String

    Public Sub New()
        _anpanchi = "顔が濡れて力が出ない"
    End Sub

    Public Sub New(batako As IBatako, jam As IJam)
        _anpanchi = "元気100倍アンパンマン"
    End Sub

    Public Sub Anpanchi() Implements IAnpanMan.Anpanchi
        Console.WriteLine(_anpanchi)
    End Sub
End Class
元気100倍アンパンマン
顔が濡れて力が出ない

おわりに

無事に元気100倍アンパンチが出来ました。

余談ですが、ジャムおじさんやバタコさんは人間じゃなかったんですね。

おわり