Results 1 to 17 of 17

Thread: Dictionary(Of Integer, "Method"?)

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Dictionary(Of Integer, "Method"?)

    Hey,

    I have a large number of methods and I need to call one of them, based on some integer. Of course I could just use a Select Case statement like so
    Code:
    Select Case someInteger
       Case 0
           Me.Method1()
       Case 1
           Me.SomeOtherMethod()
       Case 2
           Me.Method45()
       Case 3
           Me.FinalMethod()
    End Select
    (except like 5 times longer)

    But I'd rather not do that. I thought perhaps I could create a dictionary instead, where the keys are the integers, and the values are the methods.

    The problem is, I'm not sure how I should do this. I am certain it has to do with delegates, but I'm not very familiar with them...


    I've tried to declare the dictionary like so:
    Code:
    Private _MethodDictionary As New Dictionary(Of Integer, [Delegate])
    I then wasn't sure how to add a value to it... I thought I needed to use the AddressOf operator, but that doesn't seem to work:
    Code:
    _MethodDictionary.Add(0, AddressOf OnDownButtonClicked)
    It underlines the AddressOf part saying:
    'AddressOf' expression cannot be converted to 'System.Delegate' because type 'System.Delegate' is declared 'MustInherit' and cannot be created.
    Right... So why does it work in an AddHandler statement? I think all the AddressOf operator did was create a delegate that points to the method provided?

    So I then tried something else, using the Action class:
    Code:
    _MethodDictionary.Add(0, New Action(AddressOf OnDownButtonClicked))
    VS accepts this, ok great!

    But now I need to invoke this method, and I'm not sure how to do that... I could only find 'DynamicInvoke', or I could access the Method property (as a MethodInfo object) and call its Invoke method, passing in the object ("Me"). But that doesn't seem like a very good approach, I want to avoid Reflection as much as possible...


    I'm starting to think I'm going about this the wrong way, so I decided to just ask it here. I'm sure a few of you know exactly how to do this.

    Another few quite important things to note are:

    1. The thread title says VS2008, but I am actually coding in VS2010. However, I need to downgrade this project back to VS2008 when I'm done with it, so I cannot use any VS2010-only features. Whatever I use must be compatible with VS2008 when I downgrade it later.

    2. That also means, no .NET framework 4.0 stuff. In fact, I would like to keep it 2.0 if that's possible at all.


    Thanks!

  2. #2
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Dictionary(Of Integer, "Method"?)

    Would you not just add a new delegate:

    Code:
     Friend Delegate Sub DelegateThing()
     MethodDictionary.Add(0, New DelegateObject(AddressOf DelegateThing))
    Not tried it.

  3. #3
    Fanatic Member Satal Keto's Avatar
    Join Date
    Dec 2005
    Location
    Me.Location
    Posts
    518

    Re: Dictionary(Of Integer, "Method"?)

    Wouldn't it be possible to use reflection, then you could have a dictionary with the integer and a string, which stores the name of the function?

    I'm currently looking up and working on a bit of code but thought I would post this incase you know a reason why this wouldn't work for your scenario.

    Satal

  4. #4
    Fanatic Member Satal Keto's Avatar
    Join Date
    Dec 2005
    Location
    Me.Location
    Posts
    518

    Re: Dictionary(Of Integer, "Method"?)

    Ok I haven't tested this, but I think the following code should do what you're looking for, obviously if your methods needed to provide arguments for the parameters then you would have to deal with that in the appropriately commented place.

    Code:
    Imports System.Reflection
    Public Class frmTest
        Private _methodDictionary As New Dictionary(Of Integer, String)
    
        Private Sub frmTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim someInteger As Integer = 0
            Dim myAssembly As Assembly = Assembly.GetExecutingAssembly
            Dim myMethod As MethodInfo
            myMethod = myAssembly.GetModule("CurrentClassName").GetMethod(_methodDictionary.Item(someInteger))
            Dim Parameters(myMethod.GetParameters().Length - 1) As Object
            'You would set the parameters here if there are any
            myMethod.Invoke(Me, Parameters)
        End Sub
    End Class
    I hope that this helps you Nick

    Satal

    [UPDATE]
    I have used the following site as a reference, incase you want to look into this further:
    http://www.java2s.com/Code/VB/Develo...lectionAPI.htm

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Dictionary(Of Integer, "Method"?)

    Quote Originally Posted by Grimfort View Post
    Would you not just add a new delegate:

    Code:
     Friend Delegate Sub DelegateThing()
     MethodDictionary.Add(0, New DelegateObject(AddressOf DelegateThing))
    Not tried it.
    Perhaps.. But I don't have any delegates (I think ). I just have a class with a bunch of methods, and I need to call one of those methods. They are ordinary methods, and I could call them ordinarily as well, but that would result in an ugly long Select Case statement...

    Quote Originally Posted by Satal Keto View Post
    Wouldn't it be possible to use reflection, then you could have a dictionary with the integer and a string, which stores the name of the function?

    I'm currently looking up and working on a bit of code but thought I would post this incase you know a reason why this wouldn't work for your scenario.

    Satal
    Sure I could use reflection, but I don't want to. I only use Reflection when there is no other solution, and in this case I'm sure that there is. Also, reflection is slow and my application is supposed to run on a tiny little handheld computer in the end (not a mobile device though) which is probably very slow so I don't want to take any chances. Finally, if I ever changed the name of one of those methods I would have to go through the code to change the string name too, whereas I could just use VS's Rename feature to rename the method if I didn't use reflection.

  6. #6

  7. #7
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: Dictionary(Of Integer, "Method"?)

    You have two choices for your solution. I wish I always had two choices, often I only have one.

    1. Select case
    2. Reflection
    3. Large amounts of If statements (worse than select case in my opinion)


    If you refuse to use any of them I don''t know what to tell you. There is nothing wrong with a large select case. A large number of options REQUIRES it. If you don't like it then you have a good example of reflection provided by Satal.
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Dictionary(Of Integer, "Method"?)

    Quote Originally Posted by MarMan View Post
    You have two choices for your solution. I wish I always had two choices, often I only have one.

    1. Select case
    2. Reflection
    3. Large amounts of If statements (worse than select case in my opinion)


    If you refuse to use any of them I don''t know what to tell you. There is nothing wrong with a large select case. A large number of options REQUIRES it. If you don't like it then you have a good example of reflection provided by Satal.
    I don't think that's true. I'm absolutely sure that I can put a delegate (pointer to a method) in a Dictionary, and invoke it when I want. I just can't find the right syntax.

  9. #9
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Dictionary(Of Integer, "Method"?)

    If you read through this article on M-V-VM ... you see where the author did some thing similar.
    http://community.visual-basic.it/ale.../27/30571.aspx

    In fact... you can see it in use in this snip:
    Code:
        Public Sub NotifyColleagues(ByVal message As String)
    
            If String.IsNullOrEmpty(message) Then
                Throw New ArgumentException("'message' cannot be null or empty.")
            End If
    
            Dim actions = _messageToActionsMap.GetActions(message)
    
            If actions IsNot Nothing Then
                actions.ForEach(Function(action) action.DynamicInvoke())
            End If
    
        End Sub
    It looks like DynamicInvoke IS what you want...

    Curious though... if you know what number to pass in... wouldn't you know what method you're trying to invoke?

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Dictionary(Of Integer, "Method"?)

    Quote Originally Posted by techgnome View Post
    If you read through this article on M-V-VM ... you see where the author did some thing similar.
    http://community.visual-basic.it/ale.../27/30571.aspx

    In fact... you can see it in use in this snip:
    Code:
        Public Sub NotifyColleagues(ByVal message As String)
    
            If String.IsNullOrEmpty(message) Then
                Throw New ArgumentException("'message' cannot be null or empty.")
            End If
    
            Dim actions = _messageToActionsMap.GetActions(message)
    
            If actions IsNot Nothing Then
                actions.ForEach(Function(action) action.DynamicInvoke())
            End If
    
        End Sub
    It looks like DynamicInvoke IS what you want...

    Curious though... if you know what number to pass in... wouldn't you know what method you're trying to invoke?

    -tg
    Hm, I will try DynamicInvoke then when I have the time.

    I don't know which number I am passing in, as it comes from a database. What I need this for is kind of a 'dynamic onscreen keyboard', except instead of keys you get OK button, Cancel button, up, down, left, right, Menu, etc. The user must be able to choose where to place each button in the database by simply providing a 'position number'.

    I now simply store this number, the method to call when the button is clicked, and the image to draw on the button, in one Dictionary(Of Integer, KeyValuePair(Of [Delegate], Image)). When drawing, I use the image at the provided number (key), and when clicked, I invoke the method at the provided number (key). This way the keyboard is completely dynamic, and all I need to do is change the number in the database and the buttons switch places.

  11. #11
    Frenzied Member
    Join Date
    Jan 2010
    Location
    Connecticut
    Posts
    1,687

    Re: Dictionary(Of Integer, "Method"?)

    You may be right, I don't know anything about delegates. I hope you find what you want. What is the difference invoke a method from a dictionary and invoking a method through reflection?
    VB6 Library

    If I helped you then please help me and rate my post!
    If you solved your problem, then please mark the post resolved

  12. #12
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    Re: Dictionary(Of Integer, "Method"?)

    You will need to store the class name along with the method name in your dictionary. Once you have the class name and method name, use the Type.InvokeMember method to invoke it.
    Something like this:
    Code:
    Public Structure MethodInfo
        Dim className as string
        Dim methodName as string
    
        Public sub new(byval cName as string, byval mName as string)
             className = cName
             methodName = mName
        End Sub
    End structure
    
    Private methodDictionary as New Dictionary(Of Integer, methodInfo)
    
    ....................
    'add to the dictionary
    methodDictionary.Add(1, New methodInfo("WindowsApplication1.MyClass", "Foo")
    
    'Calling the method
    Dim parameters As Object() = {"hello", 123, Date.Now}
    Dim mi as methodInfo = methodDictionary(1)
    Dim tpy as Type = Type.GetType(mi.className)
    tpy.InvokeMember(mi.MethodName, Reflection.BindingFlags.InvokeMethod, Nothing, Nothing, parameters)
    Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
    - Abraham Lincoln -

  13. #13
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Dictionary(Of Integer, "Method"?)

    Don't use reflection... do it directly using a delegate. Look at the example of the lambda function in my signature for an additional example.

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'Make Dictionary
            Dim md As New Dictionary(Of String, Action(Of Object, EventArgs))
    
            'Add three things
            md.Add("Do this", AddressOf DoSomething)
            md.Add("Do this now", AddressOf DoSomethingElse)
            md.Add("Do Different", AddressOf DoSomethingDifferent)
    
            'Call those three things
            Invoke(md("Do this"), New Object() {Me, New EventArgs})
            Invoke(md("Do this now"), New Object() {Me, New EventArgs})
            Invoke(md("Do Different"), New Object() {Me, New EventArgs})
        End Sub
    
        Private Sub DoSomething(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("This what you want?")
        End Sub
    
        Private Sub DoSomethingElse(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("How about this?")
        End Sub
    
        Private Sub DoSomethingDifferent(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("Different is good")
        End Sub
    
    End Class
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  14. #14
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: Dictionary(Of Integer, "Method"?)

    Quote Originally Posted by NickThissen View Post
    Perhaps.. But I don't have any delegates (I think )
    I added one for you in my example, but the code was slightly wrong!
    Heres what it should have been.

    Code:
    Friend Delegate Sub DelegateThing()
     MethodDictionary.Add("Do Different", New DelegateThing(AddressOf YourMethod))
    That 1st line creates one to call a method without any params. But its easy to change

    Code:
    Friend Delegate Sub DelegateThing(ByVal sender As Object, ByVal e As EventArgs)
     MethodDictionary.Add("Do Different", New DelegateThing(AddressOf YourMethod))
    Last edited by Grimfort; Aug 6th, 2010 at 08:27 AM.

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Dictionary(Of Integer, "Method"?)

    Thanks guys, I got it working.

    techgnome, DynamicInvoke seems to work just fine.

    Jenner, Me.Invoke works as well. I can't see any difference between this and DynamicInvoke though..? I am using your method now but I'd like to know if there's a difference.


    AAAnyway, this is how I'm using it at the moment if you wanted to know:
    vb.net Code:
    1. Private m_objLefthandedButtons As New Dictionary(Of Integer, KeyValuePair(Of Action, Image))
    2.         Private m_objRighthandedButtons As New Dictionary(Of Integer, KeyValuePair(Of Action, Image))
    3.  
    4.         Public Sub New()
    5.  
    6.             ' This call is required by the Windows Form Designer.
    7.             InitializeComponent()
    8.  
    9.             ' Add any initialization after the InitializeComponent() call.
    10.  
    11.             m_objLefthandedButtons.Add(0, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnDownButtonClicked), My.Resources.down))
    12.             m_objLefthandedButtons.Add(1, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnOkButtonClicked), My.Resources.ok2))
    13.             m_objLefthandedButtons.Add(2, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnUpButtonClicked), My.Resources.up))
    14.             m_objLefthandedButtons.Add(3, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnCancelButtonClicked), My.Resources.back))
    15.  
    16.             m_objRighthandedButtons.Add(0, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnCancelButtonClicked), My.Resources.back))
    17.             m_objRighthandedButtons.Add(1, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnUpButtonClicked), My.Resources.up))
    18.             m_objRighthandedButtons.Add(2, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnOkButtonClicked), My.Resources.ok2))
    19.             m_objRighthandedButtons.Add(3, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnDownButtonClicked), My.Resources.down))
    20.         End Sub
    21.  
    22.         Public ReadOnly Property Buttons As Dictionary(Of Integer, KeyValuePair(Of Action, Image))
    23.             Get
    24.                 If Me.LeftHanded Then
    25.                     Return m_objLefthandedButtons
    26.                 Else
    27.                     Return m_objRighthandedButtons
    28.                 End If
    29.             End Get
    30.         End Property
    31.  
    32.         Private m_blnLeftHanded As Boolean = False
    33.         Public Property LeftHanded() As Boolean
    34.             Get
    35.                 Return m_blnLeftHanded
    36.             End Get
    37.             Set(ByVal value As Boolean)
    38.                 m_blnLeftHanded = value
    39.                 Me.Invalidate()
    40.             End Set
    41.         End Property
    42.  
    43.         Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
    44.             MyBase.OnMouseDown(e)
    45.  
    46.             Dim i As Integer = Me.GetClickedIndex(e.Location)  'gets the index (key) of the button that was clicked from the location
    47.  
    48.             ' invoke it
    49.             Me.Invoke(Me.Buttons(i).Key)
    50.  
    51.         End Sub
    52.  
    53.         Protected Overridable Sub OnUpButtonClicked()
    54.             RaiseEvent UpButtonClicked(Me, EventArgs.Empty)
    55.         End Sub
    56.  
    57.         Protected Overridable Sub OnDownButtonClicked()
    58.             RaiseEvent DownButtonClicked(Me, EventArgs.Empty)
    59.         End Sub
    60.  
    61.         Protected Overridable Sub OnOkButtonClicked()
    62.             RaiseEvent OkButtonClicked(Me, EventArgs.Empty)
    63.         End Sub
    64.  
    65.         Protected Overridable Sub OnCancelButtonClicked()
    66.             RaiseEvent CancelButtonClicked(Me, EventArgs.Empty)
    67.         End Sub

    For drawing, I do something very similar, except using the Value of the Buttons(i) object (which is the image I need to draw).

    Now this is just for left-handed vs right-handed, but in the end I can create as many buttons as I want and the user could (by editing the database) specify exactly where to place which button. The only thing that changes is their key.

  16. #16
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Dictionary(Of Integer, "Method"?)

    That's actually pretty spiffy! I like it!

    DynamicInvoke handles late-bound delegates. Basically, if you don't know the signature of your delegate at compile-time, DynamicInvoke can handle it. If you know your delegate signatures though, then Invoke works fine and is probably better for your performance as well.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  17. #17

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width