試してみると、意外と素直に書けたのでメモ。
とあるプロジェクトで、フォームが100画面ほどある VB プロジェクトを作りました。
その VB プロジェクトを起動するときに、なんらかの形で、main window を切り替えたいという要望です。
# フォームごとにアセンブリを分ければ良いのですが、
# フォーム間で参照設定が多くて、結局ひとつのアセンブリにしないと循環参照が解決されない…という現象です。
# 本当は、メモリ使用量を減らすために、個別に exe を作るのがいいんでしょうが。
フォームが 100 画面ほどある exe にパラメータを指定して、
FormCollection Form1
で起動します。
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 にします。
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 程度なので、これでよしとしますか。
