picsnet
asked on
Dynamic Parameter List
I want to call BeginInvoke with a parameter list that is unknown. It is for a generic async class. They pass me the address of a method, and an array of parameters. At runtime, I would like to be able to take the parameters out of the array and call BeginInvoke like this:
BeginInvoke(array(0),array (1),array( 2)) The problem is, I don't know how many parameters that is going to be there so I need to do it dynamically, but I haven't a clue how......
Tony
BeginInvoke(array(0),array
Tony
ASKER
that is exactly what i'm trying to not do. that is the same thing as my example except you're using an arraylist instead of an array.
Defenitely there are only two ways one is function overloading and the other is u need to add all the objects into a single storage and pass it to the function
ASKER
there has to be another way.
I thought Delegate.CreateDelegate was what I needed, but I'm not so sure now. I could get back a delegate that would have the parameter list that matched the method it is attached to, and then work with it from there. I can't call begininvoke on it though, and thats confusing me.
I've thought about dynamic methods, dynamic delegates, etc in reflection, but the reading is hard for me since it is a little out of my league.
Are those types of things not options??
I thought Delegate.CreateDelegate was what I needed, but I'm not so sure now. I could get back a delegate that would have the parameter list that matched the method it is attached to, and then work with it from there. I can't call begininvoke on it though, and thats confusing me.
I've thought about dynamic methods, dynamic delegates, etc in reflection, but the reading is hard for me since it is a little out of my league.
Are those types of things not options??
ASKER
this is one of those things that drives you insane on google
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
yeah my googling keeps heading me towards that way too, and I look at the code and run away. I was hoping desperately that the code ran to me here in a readable way
ASKER
It was impossible anyway I went about it without dynamic code generation which appears to me to mean that you have to know how to read IL, which I definitely don't. That was frustrating... all the work, that I just had to trash pretty much. My next idea was to try to do the same framework with the BackgroundWorker Component, and I was actually successful with that attempt so far. I've only tested it a couple times, so god knows what will happen later. Here is the code. Please check it out, use it, make suggestions, etc.
Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.Remoting.Me ssaging
Imports System.Windows.Forms
Public Class Async
#Region "Delegates"
Private Delegate Sub AutoCompleteEventHandler(B yRef DataSource As AutoCompleteStringCollecti on)
Private Delegate Sub DataSourceEventHandler(ByR ef DataSource As Object)
Private Delegate Sub TreeNodeEventHandler(ByRef DataSource As TreeNodeCollection)
Private Delegate Sub TreeViewEventHandler(ByRef DataSource As TreeNodeCollection)
#End Region
#Region "Private Properties"
Private WithEvents _objBackgroundWorker As BackgroundWorker
Private _objControl As Control
Private _objMethodInfo As MethodInfo
Private _objParams As Object()
Private _objProgressBar As ProgressBar
Private _DataMember As String
Private _DataValue As String
Private _RequireNetwork As Boolean
Private _UpdateEntity As Object
Private _UpdateType As UpdateTypes
#End Region
#Region "Public Properties"
Public Property Entity() As Control
Get
Return _objControl
End Get
Set(ByVal value As Control)
_objControl = value
End Set
End Property
Public Property DataMember() As String
Get
Return _DataMember
End Get
Set(ByVal value As String)
_DataMember = value
End Set
End Property
Public Property DataValue() As String
Get
Return _DataValue
End Get
Set(ByVal value As String)
_DataValue = value
End Set
End Property
Public Property ProgressBar() As ProgressBar
Get
Return _objProgressBar
End Get
Set(ByVal value As ProgressBar)
_objProgressBar = value
End Set
End Property
Public Property RequireNetwork() As Boolean
Get
Return _RequireNetwork
End Get
Set(ByVal value As Boolean)
_RequireNetwork = value
End Set
End Property
Public Property ReportsProgess() As Boolean
Get
If _objBackgroundWorker IsNot Nothing Then
Return _objBackgroundWorker.Worke rReportsPr ogress
End If
End Get
Set(ByVal value As Boolean)
If _objBackgroundWorker IsNot Nothing Then
_objBackgroundWorker.Worke rReportsPr ogress = value
End If
End Set
End Property
Public Property SupportsCancellation() As Boolean
Get
If _objBackgroundWorker IsNot Nothing Then
Return _objBackgroundWorker.Worke rSupportsC ancellatio n
End If
End Get
Set(ByVal value As Boolean)
If _objBackgroundWorker IsNot Nothing Then
_objBackgroundWorker.Worke rSupportsC ancellatio n = value
End If
End Set
End Property
Public Property UpdateEntity() As Object
Get
Return _UpdateEntity
End Get
Set(ByVal value As Object)
_UpdateEntity = value
End Set
End Property
Public Property UpdateType() As UpdateTypes
Get
Return _UpdateType
End Get
Set(ByVal value As UpdateTypes)
_UpdateType = value
End Set
End Property
#End Region
#Region "Constructors"
Public Sub New(ByRef Control As Control, ByVal UpdateType As UpdateTypes)
Me.New(Control, UpdateType, True)
End Sub
Public Sub New(ByRef Control As Control, ByVal UpdateType As UpdateTypes, ByVal RequireNetwork As Boolean)
_objBackgroundWorker = New BackgroundWorker()
_objControl = Control
_RequireNetwork = RequireNetwork
_UpdateType = UpdateType
End Sub
#End Region
#Region "Enums"
Public Enum UpdateTypes
AutoComplete
DataSource
TreeNode
TreeView
End Enum
#End Region
#Region "Public Shared Methods"
Public Shared Function GetMethodInfo(ByRef objType As Type, ByVal MethodName As String) As MethodInfo
Return objType.GetMethod(MethodNa me, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Static)
End Function
Public Shared Function GetMethodInfo(ByRef objType As Type, ByVal MethodName As String, ByVal ParamTypes As Type()) As MethodInfo
Return objType.GetMethod(MethodNa me, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Static, Nothing, ParamTypes, Nothing)
End Function
#End Region
#Region "BackgroundWorker Methods"
Private Sub _objBackgroundWorker_DoWor k(ByVal sender As Object, ByVal e As System.ComponentModel.DoWo rkEventArg s) Handles _objBackgroundWorker.DoWor k
Try
If _objControl Is Nothing Then
Throw New Exception("You must have a control to update.")
ElseIf _RequireNetwork AndAlso Not My.Computer.Network.IsAvai lable Then
Throw New Exception("A network could not be detected.")
ElseIf UpdateType = UpdateTypes.TreeNode AndAlso _UpdateEntity Is Nothing Then
Throw New Exception("Update entity is required for the type.")
End If
If (_objBackgroundWorker.Work erReportsP rogress AndAlso _objProgressBar IsNot Nothing) OrElse _objBackgroundWorker.Worke rSupportsC ancellatio n Then
ReDim Preserve _objParams(_objParams.Leng th)
_objParams(_objParams.Leng th - 1) = _objBackgroundWorker
End If
If (Not _objControl.IsDisposed() OrElse _objControl.Disposing()) AndAlso _objMethodInfo IsNot Nothing Then
If _objMethodInfo.IsStatic Then
e.Result = _objMethodInfo.Invoke(Noth ing, _objParams)
Else
e.Result = _objMethodInfo.Invoke(Acti vator.Crea teInstance (_objMetho dInfo.GetT ype(), False), _objParams)
End If
End If
Catch ex As Exception
Errors.HandleError(ex)
End Try
End Sub
Private Sub _objBackgroundWorker_Progr essChanged (ByVal sender As Object, ByVal e As System.ComponentModel.Prog ressChange dEventArgs ) Handles _objBackgroundWorker.Progr essChanged
Try
If _objProgressBar IsNot Nothing Then
_objProgressBar.Value = e.ProgressPercentage
End If
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub _objBackgroundWorker_RunWo rkerComple ted(ByVal sender As Object, ByVal e As System.ComponentModel.RunW orkerCompl etedEventA rgs) Handles _objBackgroundWorker.RunWo rkerComple ted
Try
If UpdateType = UpdateTypes.AutoComplete Then
_objControl.Invoke(New AutoCompleteEventHandler(A ddressOf BindAutoComplete), New Object() {e.Result})
ElseIf UpdateType = UpdateTypes.DataSource Then
_objControl.Invoke(New DataSourceEventHandler(Add ressOf BindDataSource), New Object() {e.Result})
ElseIf UpdateType = UpdateTypes.TreeNode Then
_objControl.Invoke(New TreeNodeEventHandler(Addre ssOf BindTreeNode), New Object() {e.Result})
ElseIf UpdateType = UpdateTypes.TreeView Then
_objControl.Invoke(New TreeViewEventHandler(Addre ssOf BindTreeView), New Object() {e.Result})
End If
Catch ex As Exception
Throw ex
Finally
_objBackgroundWorker.Dispo se()
End Try
End Sub
#End Region
#Region "Methods"
Private Sub BindAutoComplete(ByRef objDataSource As AutoCompleteStringCollecti on)
Try
Dim objControl As Object = _objControl
objControl.AutoCompleteCus tomSource = objDataSource
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub BindDataSource(ByRef objDataSource As Object)
Try
Dim objControl As Object = _objControl
objControl.DataSource = objDataSource
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub BindTreeNode(ByRef objNodeList As TreeNodeCollection)
Dim objNode As TreeNode = Nothing
Try
If _UpdateEntity IsNot Nothing AndAlso TypeOf _UpdateEntity Is TreeNode Then
objNode = CType(_UpdateEntity, TreeNode)
objNode.BeginEdit()
objNode.Nodes.Clear()
For Each objTreeNode As TreeNode In CType(objNodeList, TreeNodeCollection)
objNode.Nodes.Add(objTreeN ode)
Application.DoEvents()
Next
End If
Catch ex As Exception
Throw ex
Finally
If objNode IsNot Nothing Then objNode.EndEdit(True)
End Try
End Sub
Private Sub BindTreeView(ByRef objNodeList As TreeNodeCollection)
Dim objTree As TreeView = Nothing
Try
objTree = CType(_UpdateEntity, TreeView)
objTree.BeginUpdate()
objTree.Nodes.Clear()
For Each objTreeNode As TreeNode In objNodeList
objTree.Nodes.Add(objTreeN ode)
Application.DoEvents()
Next
Catch ex As Exception
Throw ex
Finally
If objTree IsNot Nothing Then objTree.EndUpdate()
End Try
End Sub
Public Sub Cancel()
If _objBackgroundWorker IsNot Nothing AndAlso _objBackgroundWorker.Worke rSupportsC ancellatio n Then
_objBackgroundWorker.Cance lAsync()
End If
End Sub
Public Sub RunAsync(ByVal objMethodInfo As MethodInfo, ByVal Params As Object())
_objMethodInfo = objMethodInfo
_objParams = Params
_objBackgroundWorker.RunWo rkerAsync( )
End Sub
#End Region
End Class
In Use:
Private Sub txtFindWorkOrderId_Click(B yVal sender As Object, ByVal e As System.EventArgs) Handles txtFindWorkOrderId.Click
Try
Dim objAsync As New Async(Me.txtFindWorkOrderI d, Async.UpdateTypes.AutoComp lete, True)
Dim objMethodInfo As Reflection.MethodInfo = Async.GetMethodInfo(GetTyp e(WorkOrde rs), "GetAutoCompleteIds")
objAsync.RunAsync(objMetho dInfo, New Object() {})
Catch ex As Exception
Errors.HandleError(ex)
End Try
End Sub
Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.Remoting.Me
Imports System.Windows.Forms
Public Class Async
#Region "Delegates"
Private Delegate Sub AutoCompleteEventHandler(B
Private Delegate Sub DataSourceEventHandler(ByR
Private Delegate Sub TreeNodeEventHandler(ByRef
Private Delegate Sub TreeViewEventHandler(ByRef
#End Region
#Region "Private Properties"
Private WithEvents _objBackgroundWorker As BackgroundWorker
Private _objControl As Control
Private _objMethodInfo As MethodInfo
Private _objParams As Object()
Private _objProgressBar As ProgressBar
Private _DataMember As String
Private _DataValue As String
Private _RequireNetwork As Boolean
Private _UpdateEntity As Object
Private _UpdateType As UpdateTypes
#End Region
#Region "Public Properties"
Public Property Entity() As Control
Get
Return _objControl
End Get
Set(ByVal value As Control)
_objControl = value
End Set
End Property
Public Property DataMember() As String
Get
Return _DataMember
End Get
Set(ByVal value As String)
_DataMember = value
End Set
End Property
Public Property DataValue() As String
Get
Return _DataValue
End Get
Set(ByVal value As String)
_DataValue = value
End Set
End Property
Public Property ProgressBar() As ProgressBar
Get
Return _objProgressBar
End Get
Set(ByVal value As ProgressBar)
_objProgressBar = value
End Set
End Property
Public Property RequireNetwork() As Boolean
Get
Return _RequireNetwork
End Get
Set(ByVal value As Boolean)
_RequireNetwork = value
End Set
End Property
Public Property ReportsProgess() As Boolean
Get
If _objBackgroundWorker IsNot Nothing Then
Return _objBackgroundWorker.Worke
End If
End Get
Set(ByVal value As Boolean)
If _objBackgroundWorker IsNot Nothing Then
_objBackgroundWorker.Worke
End If
End Set
End Property
Public Property SupportsCancellation() As Boolean
Get
If _objBackgroundWorker IsNot Nothing Then
Return _objBackgroundWorker.Worke
End If
End Get
Set(ByVal value As Boolean)
If _objBackgroundWorker IsNot Nothing Then
_objBackgroundWorker.Worke
End If
End Set
End Property
Public Property UpdateEntity() As Object
Get
Return _UpdateEntity
End Get
Set(ByVal value As Object)
_UpdateEntity = value
End Set
End Property
Public Property UpdateType() As UpdateTypes
Get
Return _UpdateType
End Get
Set(ByVal value As UpdateTypes)
_UpdateType = value
End Set
End Property
#End Region
#Region "Constructors"
Public Sub New(ByRef Control As Control, ByVal UpdateType As UpdateTypes)
Me.New(Control, UpdateType, True)
End Sub
Public Sub New(ByRef Control As Control, ByVal UpdateType As UpdateTypes, ByVal RequireNetwork As Boolean)
_objBackgroundWorker = New BackgroundWorker()
_objControl = Control
_RequireNetwork = RequireNetwork
_UpdateType = UpdateType
End Sub
#End Region
#Region "Enums"
Public Enum UpdateTypes
AutoComplete
DataSource
TreeNode
TreeView
End Enum
#End Region
#Region "Public Shared Methods"
Public Shared Function GetMethodInfo(ByRef objType As Type, ByVal MethodName As String) As MethodInfo
Return objType.GetMethod(MethodNa
End Function
Public Shared Function GetMethodInfo(ByRef objType As Type, ByVal MethodName As String, ByVal ParamTypes As Type()) As MethodInfo
Return objType.GetMethod(MethodNa
End Function
#End Region
#Region "BackgroundWorker Methods"
Private Sub _objBackgroundWorker_DoWor
Try
If _objControl Is Nothing Then
Throw New Exception("You must have a control to update.")
ElseIf _RequireNetwork AndAlso Not My.Computer.Network.IsAvai
Throw New Exception("A network could not be detected.")
ElseIf UpdateType = UpdateTypes.TreeNode AndAlso _UpdateEntity Is Nothing Then
Throw New Exception("Update entity is required for the type.")
End If
If (_objBackgroundWorker.Work
ReDim Preserve _objParams(_objParams.Leng
_objParams(_objParams.Leng
End If
If (Not _objControl.IsDisposed() OrElse _objControl.Disposing()) AndAlso _objMethodInfo IsNot Nothing Then
If _objMethodInfo.IsStatic Then
e.Result = _objMethodInfo.Invoke(Noth
Else
e.Result = _objMethodInfo.Invoke(Acti
End If
End If
Catch ex As Exception
Errors.HandleError(ex)
End Try
End Sub
Private Sub _objBackgroundWorker_Progr
Try
If _objProgressBar IsNot Nothing Then
_objProgressBar.Value = e.ProgressPercentage
End If
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub _objBackgroundWorker_RunWo
Try
If UpdateType = UpdateTypes.AutoComplete Then
_objControl.Invoke(New AutoCompleteEventHandler(A
ElseIf UpdateType = UpdateTypes.DataSource Then
_objControl.Invoke(New DataSourceEventHandler(Add
ElseIf UpdateType = UpdateTypes.TreeNode Then
_objControl.Invoke(New TreeNodeEventHandler(Addre
ElseIf UpdateType = UpdateTypes.TreeView Then
_objControl.Invoke(New TreeViewEventHandler(Addre
End If
Catch ex As Exception
Throw ex
Finally
_objBackgroundWorker.Dispo
End Try
End Sub
#End Region
#Region "Methods"
Private Sub BindAutoComplete(ByRef objDataSource As AutoCompleteStringCollecti
Try
Dim objControl As Object = _objControl
objControl.AutoCompleteCus
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub BindDataSource(ByRef objDataSource As Object)
Try
Dim objControl As Object = _objControl
objControl.DataSource = objDataSource
Catch ex As Exception
Throw ex
End Try
End Sub
Private Sub BindTreeNode(ByRef objNodeList As TreeNodeCollection)
Dim objNode As TreeNode = Nothing
Try
If _UpdateEntity IsNot Nothing AndAlso TypeOf _UpdateEntity Is TreeNode Then
objNode = CType(_UpdateEntity, TreeNode)
objNode.BeginEdit()
objNode.Nodes.Clear()
For Each objTreeNode As TreeNode In CType(objNodeList, TreeNodeCollection)
objNode.Nodes.Add(objTreeN
Application.DoEvents()
Next
End If
Catch ex As Exception
Throw ex
Finally
If objNode IsNot Nothing Then objNode.EndEdit(True)
End Try
End Sub
Private Sub BindTreeView(ByRef objNodeList As TreeNodeCollection)
Dim objTree As TreeView = Nothing
Try
objTree = CType(_UpdateEntity, TreeView)
objTree.BeginUpdate()
objTree.Nodes.Clear()
For Each objTreeNode As TreeNode In objNodeList
objTree.Nodes.Add(objTreeN
Application.DoEvents()
Next
Catch ex As Exception
Throw ex
Finally
If objTree IsNot Nothing Then objTree.EndUpdate()
End Try
End Sub
Public Sub Cancel()
If _objBackgroundWorker IsNot Nothing AndAlso _objBackgroundWorker.Worke
_objBackgroundWorker.Cance
End If
End Sub
Public Sub RunAsync(ByVal objMethodInfo As MethodInfo, ByVal Params As Object())
_objMethodInfo = objMethodInfo
_objParams = Params
_objBackgroundWorker.RunWo
End Sub
#End Region
End Class
In Use:
Private Sub txtFindWorkOrderId_Click(B
Try
Dim objAsync As New Async(Me.txtFindWorkOrderI
Dim objMethodInfo As Reflection.MethodInfo = Async.GetMethodInfo(GetTyp
objAsync.RunAsync(objMetho
Catch ex As Exception
Errors.HandleError(ex)
End Try
End Sub
So when u invoke with multiple parameters
Add into the ArrayList
arraylist.Add(obj1)
arraylist.Add(obj2)
arraylist.Add(obj3)
BeginInvoke(arrayList)
In the delegate function u can get using
Public Delegate Function Args1(ByVal arraylist As ArrayList)
For Each ob As Object In arraylist
Next
And if u want the number of arguments sent use
arrayList.Count