By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,449 Members | 1,601 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,449 IT Pros & Developers. It's quick & easy.

problem with Invoking an event

P: n/a
I am trying to invoke an event using reflection.

//////////////////////

public class Test
{
public event EventHandler NameChanged;

public void CallEvent()
{
EventInfo ei = GetType().GetEvent("NameChanged");

if(ei != null)
{
Type handlerType = ei.EventHandlerType;

MethodInfo invokeMethod = handlerType.GetMethod("Invoke");

object[] args = new object[] { this, EventArgs.Empty };

invokeMethod.Invoke(this, args);
}
}
}

////////////////

....but the Invoke method is blowing up with an unhandled TargetException.

Anyone got any ideas what I am dong wrong ?

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Joanna,

You say you want to invoke the *event*, and the code is trying to invoke the
*event handler*, the listener of the event. If you want to raise the event
you should call GetRaiseMethod()...

Oh, wait! Read this first:
http://www.dotnet247.com/247referenc...51/258691.aspx. Looks like you're
out of luck...

Are you trying to raise events of your own class? Then you could add
RaiseNameChanged method. If you need to raise events of BCL classes, then
you could exploit the fact that many of them use the pattern of providing a
protected On<event name> method which raises the event.

HTH,
Alexander
"Joanna Carter (TeamB)" <jo*****@nospamforme.com> wrote in message
news:eN****************@tk2msftngp13.phx.gbl...
I am trying to invoke an event using reflection.

//////////////////////

public class Test
{
public event EventHandler NameChanged;

public void CallEvent()
{
EventInfo ei = GetType().GetEvent("NameChanged");

if(ei != null)
{
Type handlerType = ei.EventHandlerType;

MethodInfo invokeMethod = handlerType.GetMethod("Invoke");

object[] args = new object[] { this, EventArgs.Empty };

invokeMethod.Invoke(this, args);
}
}
}

////////////////

...but the Invoke method is blowing up with an unhandled TargetException.

Anyone got any ideas what I am dong wrong ?

Joanna

--
Joanna Carter
Consultant Software Engineer

Nov 16 '05 #2

P: n/a
"Alexander Shirshov" <al*******@omnitalented.com> a écrit dans le message de
news: OW**************@tk2msftngp13.phx.gbl...
You say you want to invoke the *event*, and the code is trying to invoke the *event handler*, the listener of the event. If you want to raise the event
you should call GetRaiseMethod()...

Oh, wait! Read this first:
http://www.dotnet247.com/247referenc...51/258691.aspx. Looks like you're out of luck...
Yup, I already tried that :-)
Are you trying to raise events of your own class? Then you could add
RaiseNameChanged method. If you need to raise events of BCL classes, then
you could exploit the fact that many of them use the pattern of providing a protected On<event name> method which raises the event.


The problem I am trying to circumvent is the necessity for any object whose
properties are to be displayed in a TextBox, etc to have a
(PropertyName)Changed event fired to update the control. This means having
to have one explicitly named event per property.

Now, it is bad enough having to have these extra events in every class, but
also having to have a wrapper method as well is starting to detract from the
idea of 'automatic' data-aware controls.

My idea was to be able to have one method that raised the appropriate 'by
name' using something similar to the code I originally posted.

What is your opinion as to why I am getting the TargetException, because
apart from that, it would seem like I am doing all the steps that should be
necessary ?

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #3

P: n/a
> What is your opinion as to why I am getting the TargetException, because
apart from that, it would seem like I am doing all the steps that should
be
necessary ?


My guess you're getting the exception because nobody has subscribed to the
event. As I said before you're invoking the handler and not invoking the
event. In "normal" C# you'd write something like this:

if (NameChanged != null)
{
// Perform the equivalent of NameChanged(this, EventArgs.Empty);

foreach (Delegate handler in NameChanged.GetInvocationList())
{
handler.Invoke();
}
}

and your code just do this:

NameChanged.GetInvocationList()[0].Invoke();

(Compiled with Outlook Express but you should get the idea)

.....

But wait, I might have something for you! If I understand correctly you're
binding your own classes to controls and you don't want to add all
corresponding <property name>Changed events. If that's the case then have a
look at this excellent article:
http://www.interact-sw.co.uk/iangblo...propertychange

HTH,
Alexander

Nov 16 '05 #4

P: n/a
"Alexander Shirshov" <al*******@omnitalented.com> a écrit dans le message de
news: ul*************@TK2MSFTNGP15.phx.gbl...
My guess you're getting the exception because nobody has subscribed to the
event. As I said before you're invoking the handler and not invoking the
event. In "normal" C# you'd write something like this:
Well officially, the control has subscribed, but I understand that what I
was doing did not stand much chance of working.

So, I resorted to using an internal Dictionary<string, EventHandler> like
this

/////////////////////////////

public class EventTest
{
private Dictionary<string, object> values = new Dictionary<string,
object>();

protected Dictionary<string, EventHandler> events = new
Dictionary<string, EventHandler>();

public EventTest()
{
PropertyInfo[] properties = GetType().GetProperties();

foreach(PropertyInfo propInfo in properties)
{
Type[] paramTypes = new Type[] { propInfo.PropertyType };

Type testType =
typeof(TestType<>).BindGenericParameters(paramType s);

valueTypes.Add(propInfo.Name, Activator.CreateInstance(testType));
}

EventInfo[] events = GetType().GetEvents();

foreach(EventInfo ei in events)
this.events.Add(ei.Name, null);
}

private const string sChanged = "Changed";

private void AddChangedDelegate(string name, EventHandler del)
{
events[name + sChanged] += del;
}

private void RemoveChangedDelegate(string name, EventHandler del)
{
events[name + sChanged] -= del;
}

private void OnChanged(string name, EventArgs args)
{
if(events[name] != null)
events[name](this, args);
}

protected object GetValue(string name)
{
return values[name]);
}

protected void SetValue(string name, object value)
{
values[name]) = value;
OnChanged(name, EventArgs.Empty);
}

private const string sName = "Name";
private const string sAge = "Age";

public string Name
{
get { return GetValue(sName) == null ? String.Empty : (string)
GetValue(sName); }
set { SetValue(sName, value); }
}

public int Age
{
get { return (int) GetValue(sAge); }
set { SetValue(sAge, value); }
}

public event EventHandler NameChanged
{
add { AddChangedDelegate(sName, value); }
remove { RemoveChangedDelegate(sName, value); }
}
}

/////////////////////

This is much simpler, only requiring the obligatory (PropertyName)Changed
events for each property :-) + :-(

Although I am not jettisoning my code as it makes handling events not
destined for controls easier to manage.
But wait, I might have something for you! If I understand correctly you're
binding your own classes to controls and you don't want to add all
corresponding <property name>Changed events. If that's the case then have a look at this excellent article:
http://www.interact-sw.co.uk/iangblo...propertychange


Now why didn't you post that earlier !!! <vbg>

I had just finished the version above, checked the newsgroups, read this
article, picked my jaw up from the desk :-), changed my code and all is well
with the world !!!

Thank you, thank you, thank you.

I might have been doing OO design for years, but this .NET framework is just
so massive; thank goodness for the internet allowing us to 'meld minds'.

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.