|
-
Aug 6th, 2010, 04:33 AM
#1
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!
-
Aug 6th, 2010, 04:38 AM
#2
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.
-
Aug 6th, 2010, 04:38 AM
#3
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
If you find a response helpful then remember to Rate it
Personal website Sam Jenkins
-
Aug 6th, 2010, 04:46 AM
#4
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
If you find a response helpful then remember to Rate it
Personal website Sam Jenkins
-
Aug 6th, 2010, 04:48 AM
#5
Re: Dictionary(Of Integer, "Method"?)
 Originally Posted by Grimfort
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...
 Originally Posted by Satal Keto
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.
-
Aug 6th, 2010, 04:50 AM
#6
Re: Dictionary(Of Integer, "Method"?)
Ok, I'm looking forward to seeing the solution for my own reference, but unfortunately can't help you any more
If you find a response helpful then remember to Rate it
Personal website Sam Jenkins
-
Aug 6th, 2010, 07:47 AM
#7
Re: Dictionary(Of Integer, "Method"?)
You have two choices for your solution. I wish I always had two choices, often I only have one .
- Select case
- Reflection
- 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
-
Aug 6th, 2010, 07:52 AM
#8
Re: Dictionary(Of Integer, "Method"?)
 Originally Posted by MarMan
You have two choices for your solution. I wish I always had two choices, often I only have one  .
- Select case
- Reflection
- 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.
-
Aug 6th, 2010, 07:57 AM
#9
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
-
Aug 6th, 2010, 08:01 AM
#10
Re: Dictionary(Of Integer, "Method"?)
 Originally Posted by techgnome
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.
-
Aug 6th, 2010, 08:03 AM
#11
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
-
Aug 6th, 2010, 08:07 AM
#12
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 -
-
Aug 6th, 2010, 08:14 AM
#13
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
-
Aug 6th, 2010, 08:23 AM
#14
Re: Dictionary(Of Integer, "Method"?)
 Originally Posted by NickThissen
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.
-
Aug 6th, 2010, 08:24 AM
#15
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:
Private m_objLefthandedButtons As New Dictionary(Of Integer, KeyValuePair(Of Action, Image)) Private m_objRighthandedButtons As New Dictionary(Of Integer, KeyValuePair(Of Action, Image)) Public Sub New() ' This call is required by the Windows Form Designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. m_objLefthandedButtons.Add(0, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnDownButtonClicked), My.Resources.down)) m_objLefthandedButtons.Add(1, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnOkButtonClicked), My.Resources.ok2)) m_objLefthandedButtons.Add(2, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnUpButtonClicked), My.Resources.up)) m_objLefthandedButtons.Add(3, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnCancelButtonClicked), My.Resources.back)) m_objRighthandedButtons.Add(0, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnCancelButtonClicked), My.Resources.back)) m_objRighthandedButtons.Add(1, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnUpButtonClicked), My.Resources.up)) m_objRighthandedButtons.Add(2, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnOkButtonClicked), My.Resources.ok2)) m_objRighthandedButtons.Add(3, New KeyValuePair(Of Action, Image)(New Action(AddressOf OnDownButtonClicked), My.Resources.down)) End Sub Public ReadOnly Property Buttons As Dictionary(Of Integer, KeyValuePair(Of Action, Image)) Get If Me.LeftHanded Then Return m_objLefthandedButtons Else Return m_objRighthandedButtons End If End Get End Property Private m_blnLeftHanded As Boolean = False Public Property LeftHanded() As Boolean Get Return m_blnLeftHanded End Get Set(ByVal value As Boolean) m_blnLeftHanded = value Me.Invalidate() End Set End Property Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs) MyBase.OnMouseDown(e) Dim i As Integer = Me.GetClickedIndex(e.Location) 'gets the index (key) of the button that was clicked from the location ' invoke it Me.Invoke(Me.Buttons(i).Key) End Sub Protected Overridable Sub OnUpButtonClicked() RaiseEvent UpButtonClicked(Me, EventArgs.Empty) End Sub Protected Overridable Sub OnDownButtonClicked() RaiseEvent DownButtonClicked(Me, EventArgs.Empty) End Sub Protected Overridable Sub OnOkButtonClicked() RaiseEvent OkButtonClicked(Me, EventArgs.Empty) End Sub Protected Overridable Sub OnCancelButtonClicked() RaiseEvent CancelButtonClicked(Me, EventArgs.Empty) 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.
-
Aug 6th, 2010, 08:32 AM
#16
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.
-
Aug 6th, 2010, 08:35 AM
#17
Re: Dictionary(Of Integer, "Method"?)
I see, that makes sense I guess Thanks.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|