VBAでのDIコンテナ実装ガイド

こんにちは!大阪市を拠点に活動している『縁紡ぐ』の稲垣です。

SWELLを使ったホームページ制作や、Excel、ACCESS、RPAなどのシステム開発を行っています。
また、Excel、Word、Outlookの研修や、情報セキュリティ研修も行っています。身近なITの相談相手になりたいと思っています。

お気軽にお問い合わせください。

VBAでのDIコンテナ実装ガイド

目次

DIコンテナとは

DI(Dependency Injection)コンテナは、オブジェクトの依存関係を管理するためのツールです。オブジェクト指向型の言語であるJavaの開発では、DIコンテナは便利で使われています。VBAにおいては、DIコンテナと同様の機能はありませんが、似た機能を作成したいと思います。シングルトンになりますが。
シングルトンとは、ひとつのインスタンスをみんなで利用することです。

クラスでの開発は、コードの再利用性やテストの容易さを向上させるため少し大きめのシステムを作成する場合は、クラスを使うことをおススメします。実装方法も解説します。

コードの解説

今回は、DIコンテナは標準モジュールで作成で実装します。クラス名は、『DIContainar』です。

 DIコンテナの初期化

VBAの場合、辞書型を利用すると、『キー』と『オブジェクト』を関連付けて保存することができます。プライベートにして、隠蔽しておきます。


Private registry As Object ' Scripting.Dictionary を使用するためのオブジェクト

' コンストラクタ
Private Sub InitializeContainer()
    If registry Is Nothing Then
        Set registry = CreateObject("Scripting.Dictionary")
    End If
End Sub

シングルトンを取得する

' シングルトンインスタンスを取得する
Public Shared Function GetInstance() As DIContainer
    If instance Is Nothing Then
        Set instance = New DIContainer
    End If
    Set GetInstance = instance
End Function

クラス名と生成するオブジェクトの紐づけ

VBAでは、「New 変数」 で、インスタンス化する方法が調査しても不明でした。そのため、クラス名とインスタンス化するものを紐づけするために、Selectで実装しました。

' クラス名を元にインスタンスを作成
Private Function CreateInstance(classType As String) As Object
    On Error GoTo ErrorHandler

    Select Case classType
        Case "studentManager"
            Set CreateInstance = New studentManager
        Case "classManager"
            Set CreateInstance = New classManager
        ' 他のクラスがあればここに追加
        Case Else
            Err.Raise vbObjectError + 1001, "DIContainer", "未知のクラス: " & classType
    End Select
    Exit Function

ErrorHandler:
    Err.Raise vbObjectError + 1002, "DIContainer", "インスタンス作成エラー: " & Err.Description
End Function

クラスが増えた場合は、追加することで対応ができます

新規作成して登録

存在しなければ新規作成して登録します。

' 存在しなければ新規作成して登録
Public Function RegisterOrResolve(className As String, classType As String) As Object
    InitializeContainer
    If registry.Exists(className) Then
        ' 既に存在する場合はインスタンスを返す
        Set RegisterOrResolve = registry(className)
    Else
        ' 存在しない場合は新規に作成し、登録
        Dim newInstance As Object
        Set newInstance = CreateInstance(classType)
        registry.Add className, newInstance
        Set RegisterOrResolve = newInstance
    End If
End Function

インスタンスの解放

' すべてのインスタンスを解放
Public Sub ClearRegistry()
    Dim key As Variant
    For Each key In registry.Keys
        Set registry(key) = Nothing
    Next key
    registry.RemoveAll
End Sub

DIコンテナ自身の解放

' DIコンテナのインスタンスを解放する
Public Sub ReleaseContainer()
    ClearRegistry
    Set registry = Nothing
End Sub

コードの全体

' DIContainer標準モジュール
Option Explicit

Private registry As Object ' Scripting.Dictionary を使用するためのオブジェクト

' コンストラクタ
Sub InitializeContainer()
    If registry Is Nothing Then
        Set registry = CreateObject("Scripting.Dictionary")
    End If
End Sub

' クラス名を元にインスタンスを作成
Private Function CreateInstance(classType As String) As Object
    On Error GoTo ErrorHandler

    Select Case classType
        Case "studentManager"
            Set CreateInstance = New studentManager
        Case "classManager"
            Set CreateInstance = New classManager
        ' 他のクラスがあればここに追加
        Case Else
            Err.Raise vbObjectError + 1001, "DIContainer", "未知のクラス: " & classType
    End Select
    Exit Function

ErrorHandler:
    Err.Raise vbObjectError + 1002, "DIContainer", "インスタンス作成エラー: " & Err.Description
End Function

' 存在しなければ新規作成して登録
Public Function RegisterOrResolve(className As String, classType As String) As Object
    InitializeContainer
    If registry.Exists(className) Then
        ' 既に存在する場合はインスタンスを返す
        Set RegisterOrResolve = registry(className)
    Else
        ' 存在しない場合は新規に作成し、登録
        Dim newInstance As Object
        Set newInstance = CreateInstance(classType)
        registry.Add className, newInstance
        Set RegisterOrResolve = newInstance
    End If
End Function

' すべてのインスタンスを解放
Public Sub ClearRegistry()
    Dim key As Variant
    For Each key In registry.Keys
        Set registry(key) = Nothing
    Next key
    registry.RemoveAll
End Sub

' DIコンテナのインスタンスを解放する
Public Sub ReleaseContainer()
    ClearRegistry
    Set registry = Nothing
End Sub

DIContainerを利用する方法例

Sub ExampleUsage()
    Dim studentMgr As Object
    Dim classMgr As Object

    ' DIコンテナを使用してインスタンスを登録または解決
    Set studentMgr = RegisterOrResolve("StudentManager", "studentManager")
    Set classMgr = RegisterOrResolve("ClassManager", "classManager")

    ' 使用例
    studentMgr.SomeMethod
    classMgr.SomeMethod

    ' インスタンスを解放
    ReleaseContainer
End Sub

このRegisterOrResolveを呼び出すときに、クラス名とクラスタイプ名を渡すと、最初に作成した辞書に、登録がされている場合は、辞書に登録されているインスタンスを返却します。

辞書に登録がない場合は、先ほど作成した、CreateInstanceメソッドを呼び出しインスタンス化して辞書に登録をします。

DIコンテナからインスタンスを取得する

Set studentMg = DIContainar.RegisterOrResolve("studentManager", "studentManager")

これで、DIコンテナからインスタンスを取得することができます。

まとめ

VBAでDIコンテナを実装する方法をご紹介しました。クラスで開発することで、保守性が向上します。業務効率化を目指す方には特におすすめです。ぜひ、実際にコードを試してみてください。

記事を書いた人

稲垣

  • Excel、ACCESSでのシステム開発が得意
  • ITスキルを共有し実践的に学びながら成長する人を見るのが幸せ
  • 自家焙煎するほどのコーヒー好き
  • 使用言語 VBA、Python、Javascript、Java、HTML、CSS etc.
  • 保有資格 Kintoneアソシエイト、日商簿記検定2級、マンション管理士、管理業務主任者、情報セキュリティマネジメント、ExcelVBA etc.
  • 業務フロー図の作成や業務時間分析を通して、効率化ポイントを探る人
  • お客様にとって本当に良いことかを第一に考える人
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次