秘密基地、どこに作った?

VBCodeProviderを使用し、文字列で入力したVBのコードを動的に実行可能なことを最近知りましたが、
このコードからプログラム本体のForm上のテキストボックス等にアクセスする方法はありますか?

下記リンク
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.ph …
に掲載されたコードを改造してMsgBoxの部分を、プロジェクトに追加したForm1上のTextBoxに表示するように
変更しました(単純に
Form1.TextBox1.Text="xxx"
と変更したのみ)。Form1のTextBox1に表示が出ることを期待しましたが、実行するとCompileAssemblyFromSourceでエラーが戻り、
oCompilerResultsは"名前 'Form1' は宣言されていません。"という内容となります。

文字列のコードに本体プログラムを参照させる記述が必要なんだろうと思いますが、その方法が分かっていません。

以上。よろしくお願いします。

A 回答 (1件)

直接参照させることは出来ないでしょうね。


オブジェクト指向に関する理解が十分に出来ているなら
=======================

Option Explicit On
Option Strict On
Option Compare Binary
'Option Infer Off


Imports System.CodeDom.Compiler
Imports System.Reflection
Imports System.Text

Class DynamicCompileAndRun
Inherits System.Windows.Forms.Form


Private TextBox1 As System.Windows.Forms.TextBox

Sub New()

TextBox1 = New System.Windows.Forms.TextBox
Me.Controls.Add(TextBox1)

End Sub

Shared Sub main()

Dim test1 As DynamicCompileAndRun
test1 = New DynamicCompileAndRun

'文字列リテラルとして書くと結構読みづらいので外部のファイルにすることにした。
Dim SR As System.IO.StreamReader = Nothing
try
SR = New System.IO.StreamReader("./Q4654347D-1.txt",System.Text.Encoding.GetEncoding(65001))
Dim sSource As String = SR.ReadToEnd()

'コンパイルを実行する
Dim oCompilerParameters As New CompilerParameters
oCompilerParameters.GenerateExecutable = False
oCompilerParameters.GenerateInMemory = True
'参照として追加
oCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")

Dim oVBCompiler As New VBCodeProvider
Dim oCompilerResults As CompilerResults
oCompilerResults = oVBCompiler.CompileAssemblyFromSource(oCompilerParameters, sSource)

'動的コンパイルしたソースにエラーがあった場合、エラーを表示して、終了
If oCompilerResults.Errors.Count >= 1 Then
Debug.Print("動的に与えられたソースコードにコンパイルエラーがありました。")
For Each oCompilerError As System.CodeDom.Compiler.CompilerError In oCompilerResults.Errors
Debug.Print(oCompilerError.ToString())
Next
MsgBox("ソースコードにエラーがあります。イミディエイトウィンドウにエラーを表示しました。")
Exit Sub
End If

'コンパイルしたアセンブリをインスタンス化して実行
Dim oDynamicCompiledAssembly As Assembly = oCompilerResults.CompiledAssembly
Dim oDynamicCompiledClassType As Type = oDynamicCompiledAssembly.GetType("DynamicClass")
Dim oDynamicCompiledMethodInfo As MethodInfo = oDynamicCompiledClassType.GetMethod("DynamicMethod")
Dim oDynamicCompiledInstance As Object = Activator.CreateInstance(oDynamicCompiledClassType)
oDynamicCompiledMethodInfo.Invoke(oDynamicCompiledInstance, New Object(){test1.GetTextBox()})

test1.ShowDialog()



Catch e As System.IO.FileNotFoundException
Debug.Print(e.StackTrace)
Catch e As System.IO.IOException
Debug.Print(e.StackTrace)
Finally
SR.Close()
End Try




End Sub

Public Function GetTextBox() As System.Windows.Forms.TextBox
return TextBox1
End Function
End Class

===============Q4654347D-1.txt==============
Option Explicit
Option Compare Binary
Option Strict On
'Option Infer Off

Public Class DynamicClass
Sub DynamicMethod(TB1 As System.Windows.Forms.TextBox)
TB1.text = "ほげ"
End Sub
End Class
======================
とか引数でSystem.Windows.Forms.TextBoxを渡せるようにして実行します。

#自分の場合、扱い辛いので、独自に呼び出し元と動的コンパイルするソースのインターフェースを決め、それらだけ宣言したDLLを作成し,
呼び出し元プログラムと動的コンパイルするソースの両方で参照するようにして別々に作ります。独自のクラスとして扱え、どちらか一方が完成している必要がなさそうなので。

#この回答を考えるに当たって事前に,(動的コンパイルではなく)コンパイル済みのDLLのものを呼び出し元から呼べるようにすることで、DLL差し替えで動作を変えられる仕組みを作成していました。

この回答への補足

himajin100000様
回答ありがとうございます。

教えていただいたコードで動きました。引数でわたせばよいのですね。

あと、すみませんが以下の部分についてはイメージできませんでした。
引用---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#自分の場合、扱い辛いので、独自に呼び出し元と動的コンパイルするソースのインターフェースを決め、それらだけ宣言したDLLを作成し,
呼び出し元プログラムと動的コンパイルするソースの両方で参照するようにして別々に作ります。独自のクラスとして扱え、どちらか一方が完成している必要がなさそうなので。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
もうすこし詳しく教えていただけないでしょうか。

補足日時:2009/01/27 10:30
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報