Assembly.LoadFrom を使って別のアセンブリにあるフォームを起動する

試してみると、意外と素直に書けたのでメモ。

とあるプロジェクトで、フォームが100画面ほどある VB プロジェクトを作りました。
その VB プロジェクトを起動するときに、なんらかの形で、main window を切り替えたいという要望です。

# フォームごとにアセンブリを分ければ良いのですが、
# フォーム間で参照設定が多くて、結局ひとつのアセンブリにしないと循環参照が解決されない…という現象です。
# 本当は、メモリ使用量を減らすために、個別に exe を作るのがいいんでしょうが。

フォームが 100 画面ほどある exe にパラメータを指定して、

1
FormCollection Form1

で起動します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Module Startup
    Public Sub main(ByVal args() As String)
        ' 引数からクラス名を取得
        Dim cname As String = args(0)
        cname = "FormCollection." + cname
        ' 指定フォームを作成
        Dim t As Type = Type.GetType(cname)
        If t IsNot Nothing Then
            Dim obj As Object = System.Activator.CreateInstance(t)
            If obj IsNot Nothing Then
                ' アプリケーションを起動
                Dim frm As Form = CType(obj, Form)
                Application.Run(frm)
            End If
        End If
    End Sub
End Module

ここでは、namespace が FormCollection なので、これを追加しています。

さて、本体 exe の名前を変えて Form1.exe, Form2.exe, Form3.exe … と作ってもよいのですが、本体 exe のサイズが大きい場合には、コピーすると HDD 容量が必要になります。

なので、起動用に別のプロジェクトを作って、次のような startup にします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Module Startup
    Public Sub main(ByVal args() As String)
        ' クラス名を実行ファイルから取得
        Dim cname As String = Application.ExecutablePath
        cname = cname.Substring( _
            cname.LastIndexOf("\") + 1, _
            cname.Length - cname.LastIndexOf("\") - 1)
        cname = cname.Substring(0, cname.LastIndexOf("."))
        cname = "FormCollection." + cname
        ' アセンブリのロード
        Dim asm As System.Reflection.Assembly = _
            System.Reflection.Assembly.LoadFrom("FormCollection.exe")
        ' 指定フォームを作成
        Dim t As Type = asm.GetType(cname)
        If t IsNot Nothing Then
            Dim obj As Object = System.Activator.CreateInstance(t)
            If obj IsNot Nothing Then
                ' アプリケーションを起動
                Dim frm As Form = CType(obj, Form)
                Application.Run(frm)
            End If
        End If
    End Sub
End Module

ってな風なのを考えた訳ですが、本体のロード時間を考えると必要なフォームだけをかき集めた exe を作るのがベストですね。
まぁ、本体が 3 MB 程度なので、これでよしとしますか。

カテゴリー: 開発, VB パーマリンク