Link to home
Start Free TrialLog in
Avatar of picsnet
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
Avatar of udhayakumard
udhayakumard
Flag of India image

Public Delegate Function Args(ByVal arg1 As System.Collections.ArrayList)

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
Avatar of picsnet
picsnet

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
Avatar of picsnet

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??
Avatar of picsnet

ASKER

this is one of those things that drives you insane on google
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of picsnet

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
Avatar of picsnet

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.Messaging
Imports System.Windows.Forms

Public Class Async

#Region "Delegates"

  Private Delegate Sub AutoCompleteEventHandler(ByRef DataSource As AutoCompleteStringCollection)
  Private Delegate Sub DataSourceEventHandler(ByRef 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.WorkerReportsProgress
      End If
    End Get
    Set(ByVal value As Boolean)
      If _objBackgroundWorker IsNot Nothing Then
        _objBackgroundWorker.WorkerReportsProgress = value
      End If
    End Set
  End Property

  Public Property SupportsCancellation() As Boolean
    Get
      If _objBackgroundWorker IsNot Nothing Then
        Return _objBackgroundWorker.WorkerSupportsCancellation
      End If
    End Get
    Set(ByVal value As Boolean)
      If _objBackgroundWorker IsNot Nothing Then
        _objBackgroundWorker.WorkerSupportsCancellation = 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(MethodName, 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(MethodName, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Static, Nothing, ParamTypes, Nothing)

  End Function

#End Region

#Region "BackgroundWorker Methods"

  Private Sub _objBackgroundWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles _objBackgroundWorker.DoWork

    Try

      If _objControl Is Nothing Then
        Throw New Exception("You must have a control to update.")
      ElseIf _RequireNetwork AndAlso Not My.Computer.Network.IsAvailable 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.WorkerReportsProgress AndAlso _objProgressBar IsNot Nothing) OrElse _objBackgroundWorker.WorkerSupportsCancellation Then
        ReDim Preserve _objParams(_objParams.Length)
        _objParams(_objParams.Length - 1) = _objBackgroundWorker
      End If

      If (Not _objControl.IsDisposed() OrElse _objControl.Disposing()) AndAlso _objMethodInfo IsNot Nothing Then
        If _objMethodInfo.IsStatic Then
          e.Result = _objMethodInfo.Invoke(Nothing, _objParams)
        Else
          e.Result = _objMethodInfo.Invoke(Activator.CreateInstance(_objMethodInfo.GetType(), False), _objParams)
        End If
      End If

    Catch ex As Exception

      Errors.HandleError(ex)

    End Try

  End Sub

  Private Sub _objBackgroundWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles _objBackgroundWorker.ProgressChanged

    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_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _objBackgroundWorker.RunWorkerCompleted

    Try

      If UpdateType = UpdateTypes.AutoComplete Then
        _objControl.Invoke(New AutoCompleteEventHandler(AddressOf BindAutoComplete), New Object() {e.Result})
      ElseIf UpdateType = UpdateTypes.DataSource Then
        _objControl.Invoke(New DataSourceEventHandler(AddressOf BindDataSource), New Object() {e.Result})
      ElseIf UpdateType = UpdateTypes.TreeNode Then
        _objControl.Invoke(New TreeNodeEventHandler(AddressOf BindTreeNode), New Object() {e.Result})
      ElseIf UpdateType = UpdateTypes.TreeView Then
        _objControl.Invoke(New TreeViewEventHandler(AddressOf BindTreeView), New Object() {e.Result})
      End If

    Catch ex As Exception

      Throw ex

    Finally

      _objBackgroundWorker.Dispose()

    End Try

  End Sub

#End Region

#Region "Methods"

  Private Sub BindAutoComplete(ByRef objDataSource As AutoCompleteStringCollection)

    Try

      Dim objControl As Object = _objControl
      objControl.AutoCompleteCustomSource = 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(objTreeNode)
          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(objTreeNode)
        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.WorkerSupportsCancellation Then
      _objBackgroundWorker.CancelAsync()
    End If

  End Sub

  Public Sub RunAsync(ByVal objMethodInfo As MethodInfo, ByVal Params As Object())

    _objMethodInfo = objMethodInfo
    _objParams = Params

    _objBackgroundWorker.RunWorkerAsync()

  End Sub

#End Region

End Class

In Use:

 Private Sub txtFindWorkOrderId_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtFindWorkOrderId.Click

    Try

      Dim objAsync As New Async(Me.txtFindWorkOrderId, Async.UpdateTypes.AutoComplete, True)
      Dim objMethodInfo As Reflection.MethodInfo = Async.GetMethodInfo(GetType(WorkOrders), "GetAutoCompleteIds")

      objAsync.RunAsync(objMethodInfo, New Object() {})

    Catch ex As Exception

      Errors.HandleError(ex)

    End Try

  End Sub