Solved

CreateInstance points to wrong function ...

Posted on 2008-10-28
9
277 Views
Last Modified: 2013-12-27
Hi,

I like to create some buttons dynamic with the NET CF2 (Custom Controls) and also delegate them dynamic to an event.
So I get the hint how to use CreateInstance to delegte to a function at runtime.
At all it works but one problem is there I can't solve - all of my buttons pint to the same function, the last one I use - in this case My4_Click

So can somebody please point me the problem why any button points to the same function?
When I debug I see that the CreateInstance contains the right function name.

Can somebody help please?

Thanks,

Andre
namespace mynamespace
{
public sealed class myfunctions
{
public static void My1_Click(object sender, EventArgs e)
{
MessageBox.Show("Funktion 1");
}
 
public static void My2_Click(object sender, EventArgs e)
{
MessageBox.Show("Funktion 2");
}
 
public static void My3_Click(object sender, EventArgs e)
{
MessageBox.Show("Funktion 3");
}
 
public static void My4_Click(object sender, EventArgs e)
{
MessageBox.Show("Funktion 4");
}
}
}
 
namespace mynamespace
{
public partial class Form1 : Form
{
 
Type TargetScr;
object TargetObj;
MethodInfo TargetMethod;
EventHandler[] TargetHandler = new EventHandler[10];
 
public Form1()
{
TargetScr = Type.GetType("mynamespace.myfunctions");
for(int i=0;i<4;i++)
{
Button but = new Button();
...
TargetObj = Activator.CreateInstance(TargetScr);
TargetMethod = TargetObj.GetType().GetMethod("My" + i.ToString() + "_Click");
TargetHandler[ i ] = delegate(object s, EventArgs e)
{
TargetMethod.Invoke(this, new object[] { s, e });
};
but.GetType().GetEvent("Click").AddEventHandler(but, TargetHandler[ i ]);
}
}
}
}

Open in new window

0
Comment
Question by:andre72
  • 5
  • 4
9 Comments
 
LVL 19

Expert Comment

by:drichards
ID: 22827785
You are using the variable TargetMethod inside the anonymous delegate.  It ends with the value of the last method retrieved from GetMethod.  Not immediately sure of a way to fix it.
0
 

Author Comment

by:andre72
ID: 22829208
Ok, I see the matter but I need a solution. Maybe there's an other way to get a simular result - to give any of the button it's own Event?
0
 
LVL 19

Expert Comment

by:drichards
ID: 22830781
Normally, you'd just do:

   but.Click += new EventHandler(My1_Click);

Unfortunately, this won't work in a loop like you're doing because you can't use a MthodInfo instance to create the event handler delegate.  You'd need to special case each iteration to assign the correct function.  I'll think about how you might do what you're attempting with the loop and reflection there.
0
How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

 

Author Comment

by:andre72
ID: 22830824
I can't use this - in this case My1_Click has to be an Object but I've only the name (as a string) of the function. So I need a delegate because I've to get the function first...
0
 

Author Comment

by:andre72
ID: 22831033
I've the solution - just use the delegate in it's own function ... Use it's in a loop will overwrite the stack with every loop - I don't know why ... But when you call a function the delegate will be stored when you leave the funktion ... Thanks at all
0
 
LVL 19

Expert Comment

by:drichards
ID: 22836675
Yes, that should work.  The delegate captures a reference to the outer variable when it is created, so if you create the delegate in a separate function with a local variable which I assume you pass in as a parameter, the delegate captures a reference to the function local which will be different on each call and not overwritten like the class member variable you were using previously.
0
 
LVL 19

Expert Comment

by:drichards
ID: 22837587
And after some yoga to relax the mind and body...

You don't need an extra method.  If you just make TargetMethod local to the loop you get the same effect.  In fact, why are any of those variables class members since you don't need them except to set up the buttons?  I've included some code that streamlines your function a bit, doesn't introduce an extra function, and eliminates what appear to be unnecessary items, though since I don't know your design you may need them after all.
namespace mynamespace
{
    public partial class Form1 : Form
    {
        EventHandler[] TargetHandler = new EventHandler[10];
 
        public Form1()
        {
            // Only need one instance of the class...
            TargetObj = Activator.CreateInstance(typeof(myfunctions));
            for (int i = 0; i < 4; i++)
            {
                Button but = new Button();
                ...
                MethodInfo TargetMethod = TargetObj.GetType().GetMethod("My" + (i+1).ToString() + "_Click");
                TargetHandler[i] = delegate(object s, EventArgs e)
                {
                    TargetMethod.Invoke(this, new object[] { s, e });
                };
                but.GetType().GetEvent("Click").AddEventHandler(but, TargetHandler[i]);
            }
        }
    }
}

Open in new window

0
 

Author Comment

by:andre72
ID: 22838800
Have you tried it out? I'd looked for a solution for two days and stand a couple of hours with, make the MethodInfo to an Array,make TargetObj to an Array. TargetObj outside the loop (like in your example) , tried MethodInfo TargetMethod = TargetScr.GetMethod("My" + (i+1).ToString() + "_Click"); and so on... I tried anything in the time to make it work - and ever the same result ... So I'm nearly sure that I'd tried out only one instance with the same result ...
0
 
LVL 19

Accepted Solution

by:
drichards earned 250 total points
ID: 22839151
Yes, I ran the code as shown except that I was not assigning the delegates to a button click.  I just cycled through the handler array after setting all the elements to verify that they each invoked the correct method in myfunctions.

If you are not doing anything with the array, you don't really need it since in your case the buttons hold on to the event delegates.  
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface: This article is part of a series focused on cross platform mobile app development (specifically Android and iOS) using the Alloy framework and Titanium Studio made by Appcelerator (https://www.appcelerator.com/). This article presumes a wor…
In this article we will discuss all things related to StageFright bug, the most vulnerable bug of android devices.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

685 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question