VB.NET2005です。
ユーザ共通関数へのパラメータとして”関数”を渡したいのですが、
受け取り側の型をどうすればよいのか分かりません…
フォームForm1にSyori1という関数
-----------
Private Sub Syori1()
〜
End Sub
-----------
があります。
ユーザ共通関数
-----------
Public Sub ComSyori1(ByRef ParSyori As ????)
Call ParSyori()
※条件により実行する関数が違う
End Sub
-----------
を定義し、
これをフォームForm1から
-----------
Call ComSyori1(Me.Syori1)
-----------
といった具合に呼び出したいのですが、
受け側の????部分が分かりません。
そもそもそういった事が出来るのかどうか分かりませんが、
教えて下さい。
私なりに調べましたところ
Action(Of T)(obj As T)が該当する?ように思いますが、
使用方法が分かりません。
全く違っていたらすみません…
何卒よろしくお願い致します。
デリゲードで渡せばよいのでは?(ByRef関係ないと思うけど)
>>Action(Of T)(obj As T)が該当する?ように思いますが、
これは、MSDNには
>>このデリゲートは、Array.ForEach メソッドおよび List.ForEach メソッドによって、
>>配列またはリストの各要素に対して操作を実行する場合に使用されます
となっているので、関数にも依りますが、違うのでは。
よくあるやつは、
Imports System
Imports System.Collections.Generic
Public Class Form1
Private Class ShoriAll
Shared Function Shori1(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
Shared Function Shori2(ByVal x As Integer, ByVal y As Integer) As Integer
Return x * y
End Function
Shared Function Shori3(ByVal x As Integer, ByVal y As Integer) As Integer
Return CInt(x ^ y)
End Function
End Class
Private Delegate Function DelegateShori(ByVal x As Integer, ByVal y As Integer) As Integer
Private Function Shori(ByVal x As Integer, ByVal y As Integer, ByVal Mydelegate As DelegateShori) As Integer
Return Mydelegate(x, y)
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori1))
Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori2))
Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori3))
End Sub
End Class
こんなのかな。
お返事ありがとうございます。
”デリゲート”恥ずかしながら初めて知りました。
見よう見まねで動的にメソッドを実行する事は出来たのですが、
次のようにイベントハンドラを追加する共通処理で
メソッドを登録するにはどうすればよいか教えて下さい。
現在、フォーム毎に初期処理にて
----------------------------------------------
フォーム1
Private Sub EventHandler_Add()
Dim WkControl As Control
For Each WkControl In Me.Controls
AddHandler WkControl.Enter, AddressOf Me.All_Enter
End For
End Sub
Private Sub All_Enter(ByVal sender As Object, ByVal e As System.EventArgs)
〜略〜
End Sub
----------------------------------------------
といった具合に(動的に)Enterイベントハンドラを追加しています。
ところがフォーム毎に毎回同じコードを記述し実行していますので
これを共通モジュールに移設し、必要な情報(フォーム、
関数ポインタ?)をパラメータとして渡すことで
共通化を図りたいと思っています。
----------------------------------------------
共通モジュール
Public Sub EventHandler_Add(ByRef ParForm As Form)
Dim WkControl As Control
For Each WkControl In ParForm.Controls
AddHandler WkControl.Enter, AddressOf ********
End For
End Sub
----------------------------------------------
********の部分は各フォームの”All_Enter”という関数を
登録したいのですが、どうすればよいですか?
何卒よろしくお願い致します。
> Public Sub EventHandler_Add(ByRef ParForm As Form)
ここで、ByRef にする必要は無いかと。
(むしろ ByVal にすべきかと思いますが)
> For Each WkControl In Me.Controls
これですと、フォーム直下のコントロールは対象になりますが、
Panel や GroupBox などの下にあるコントロールが対象外と
なるような気がしますが、それで良いのでしょうか?
> End For
文法エラーかと。
> ********の部分は各フォームの”All_Enter”という関数を
> 登録したいのですが、どうすればよいですか?
=== (案1) 共通モジュールに、デリゲートを渡す ===
Public Sub EventHandler_Add(ByVal target As Form, ByVal enterMethod As EventHandler)
For Each childControl As Control In target.Controls
AddHandler childControl.Enter, EnterMethod
Next
End Sub
----
Public Class Form1
Private Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs)
'処理
End Sub
End Class
=== (案2) All_Enter を、インターフェイスとして公開しておく ===
Interface IEnter
Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs)
End Interface
----
Public Sub EventHandler_Add(ByVal target As IEnter)
If TypeOf target Is Form Then
For Each childControl As Control In DirectCast(target, Control).Controls
AddHandler childControl.Enter, AddressOf target.All_Enter
Next
End If
End Sub
----
Public Class Form1
Implements IEnter
Private Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs) Implements IEnter.All_Enter
'処理
End Sub
End Class
=== (案3) Private な All_Enter メソッドに無理矢理アクセス(非推奨) ===
Public Sub EventHandler_Add(ByVal target As Form)
Dim method As System.Reflection.MethodInfo = target.GetType().GetMethod( _
"All_Enter", _
System.Reflection.BindingFlags.Public _
Or System.Reflection.BindingFlags.NonPublic _
Or System.Reflection.BindingFlags.Instance _
Or System.Reflection.BindingFlags.IgnoreCase _
Or System.Reflection.BindingFlags.DeclaredOnly, _
System.Type.DefaultBinder, _
New Type() {GetType(Object), GetType(EventArgs)}, _
Nothing)
If method IsNot Nothing Then
Dim enterDelegate As EventHandler = System.Delegate.CreateDelegate(GetType(EventHandler), target, "All_Enter", True)
For Each childControl As Control In DirectCast(target, Control).Controls
AddHandler childControl.Enter, enterDelegate
Next
End If
End Sub
お返事ありがとうございました。
また開発マシンとネット環境マシンが異なりコピペ出来ず手打ちしたため、
文法エラーで申し訳ございませんでした。
PanelとGroupBoxに対するコードも実際は入っていたのですが、
(コピペも出来ませんでしたし、)本筋に関係なかったため
勝手に割愛しておりました。
ご心配をお掛けしてすみませんでした。
なお本題の件は案1でばっちりです。
魔界の仮面弁士様にはいつも助けられてばかりで
心から尊敬致しております。
本当にありがとうございました。
ツイート | ![]() |