How to Verify if EventHandler for ValueChanged has been set?

R

richard.martino

I have a huge Windows desktop application with over 100 individual
controls, like TextBox, NumericUpDown, ComboBox, etc.

I want each one to have its ValueChanged (or TextChanged) event
handler set, like:

-----------

System.Windows.Forms.TextBox cityTextBox;

cityTextBox = new TextBox();
cityTextBox.TextChanged += new EventHandler(cityTextBox_TextChanged);

-----------

I can loop through all of the controls of the application starting
with this.Controls and, recursively their children, finding everyone
of my 100 individual controls.

I want my software to verify if I have every TextChanged or
ValueChanged event handler set.

Any clues?

Thanks
 
N

Nicholas Paldino [.NET/C# MVP]

Richard,

You would have to use reflection for this, as you don't have access to
the event handler list from outside the instance that exposes the event.

You would have to look for the backing field for the delegate, but the
thing is, there is no guaranteed linking between that field and the event
exposed. For the standard event implementation (no add/remove handlers), it
should work, but you might run into some custom add/remove handlers and it
won't be that easy to figure out what the backing field for the event is.

Are you doing this for unit testing, or within your app? If you are
doing it within your app, I would recommend making this a unit test or maybe
a custom rule for FxCop.
 
R

richard.martino

Richard,

    You would have to use reflection for this, as you don't have access to
the event handler list from outside the instance that exposes the event.

    You would have to look for the backing field for the delegate, but the
thing is, there is no guaranteed linking between that field and the event
exposed.  For the standard event implementation (no add/remove handlers), it
should work, but you might run into some custom add/remove handlers and it
won't be that easy to figure out what the backing field for the event is.

    Are you doing this for unit testing, or within your app?  If you are
doing it within your app, I would recommend making this a unit test or maybe
a custom rule for FxCop.

--
          - Nicholas Paldino [.NET/C# MVP]
          - (e-mail address removed)




I have a huge Windows desktop application with over 100 individual
controls, like TextBox, NumericUpDown, ComboBox, etc.
I want each one to have its ValueChanged (or TextChanged) event
handler set, like:

System.Windows.Forms.TextBox cityTextBox;
cityTextBox = new TextBox();
cityTextBox.TextChanged += new EventHandler(cityTextBox_TextChanged);

I can loop through all of the controls of the application starting
with this.Controls and, recursively their children, finding everyone
of my 100 individual controls.
I want my software to verify if I have every TextChanged or
ValueChanged event handler set.
Any clues?
Thanks- Hide quoted text -

- Show quoted text -

Nicholas:

Yes, I have tried reflection as follows:

----------

using System.Reflection;

System.Type type = cityTextBox.GetType();

EventInfo eventInfo = type.GetEvent("TextChanged",
BindingFlags.Instance | BindingFlags.Public);

MethodInfo methodInfo = eventInfo.GetRaiseMethod(true);

//
// However, methodInfo always comes back null.
//
 
N

Nicholas Paldino [.NET/C# MVP]

Richard,

From the remarks of the documentation for GetRaiseMethod:

This method returns a null reference (Nothing in Visual Basic) for events
declared with the C# event keyword or the Visual Basic Event keyword. This
is because the C# and Visual Basic compilers do not generate such a method.

Because there is no guarantee about how the delegate chain is stored for
the event (basically, it's like a property, you don't know what is being
used to store what is returned to you when you call the property), there is
really no way to get that list for inspection with certainty.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Richard,

You would have to use reflection for this, as you don't have access to
the event handler list from outside the instance that exposes the event.

You would have to look for the backing field for the delegate, but the
thing is, there is no guaranteed linking between that field and the event
exposed. For the standard event implementation (no add/remove handlers),
it
should work, but you might run into some custom add/remove handlers and it
won't be that easy to figure out what the backing field for the event is.

Are you doing this for unit testing, or within your app? If you are
doing it within your app, I would recommend making this a unit test or
maybe
a custom rule for FxCop.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I have a huge Windows desktop application with over 100 individual
controls, like TextBox, NumericUpDown, ComboBox, etc.
I want each one to have its ValueChanged (or TextChanged) event
handler set, like:

System.Windows.Forms.TextBox cityTextBox;
cityTextBox = new TextBox();
cityTextBox.TextChanged += new EventHandler(cityTextBox_TextChanged);

I can loop through all of the controls of the application starting
with this.Controls and, recursively their children, finding everyone
of my 100 individual controls.
I want my software to verify if I have every TextChanged or
ValueChanged event handler set.
Any clues?
Thanks- Hide quoted text -

- Show quoted text -

Nicholas:

Yes, I have tried reflection as follows:

----------

using System.Reflection;

System.Type type = cityTextBox.GetType();

EventInfo eventInfo = type.GetEvent("TextChanged",
BindingFlags.Instance | BindingFlags.Public);

MethodInfo methodInfo = eventInfo.GetRaiseMethod(true);

//
// However, methodInfo always comes back null.
//
 
G

Guest

If you still going to use reflection, you can use something like that:

private bool AreListenersAdded(TextBox control, string eventName)
{
var controlType = control.GetType();

var fields = controlType.GetFields(BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance);
var eventField = fields.SingleOrDefault(f => f.Name == "Event" +
eventName);
if (eventField != null)
{
var eventsProperty = (typeof(Control)).GetProperty("Events",
BindingFlags.Instance | BindingFlags.NonPublic);
var events = eventsProperty.GetValue(control, null) as
EventHandlerList;
if (events != null)
{
var textChangedEvent = eventField.GetValue(control);
var eventDelegate = events[textChangedEvent];
if (eventDelegate != null)
return eventDelegate.GetInvocationList().Length > 0;
}

}


return false;
}

Richard,

You would have to use reflection for this, as you don't have access
to
the event handler list from outside the instance that exposes the event.

You would have to look for the backing field for the delegate, but
the
thing is, there is no guaranteed linking between that field and the event
exposed. For the standard event implementation (no add/remove handlers),
it
should work, but you might run into some custom add/remove handlers and
it
won't be that easy to figure out what the backing field for the event is.

Are you doing this for unit testing, or within your app? If you are
doing it within your app, I would recommend making this a unit test or
maybe
a custom rule for FxCop.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I have a huge Windows desktop application with over 100 individual
controls, like TextBox, NumericUpDown, ComboBox, etc.
I want each one to have its ValueChanged (or TextChanged) event
handler set, like:

System.Windows.Forms.TextBox cityTextBox;
cityTextBox = new TextBox();
cityTextBox.TextChanged += new EventHandler(cityTextBox_TextChanged);

I can loop through all of the controls of the application starting
with this.Controls and, recursively their children, finding everyone
of my 100 individual controls.
I want my software to verify if I have every TextChanged or
ValueChanged event handler set.
Any clues?
Thanks- Hide quoted text -

- Show quoted text -

Nicholas:

Yes, I have tried reflection as follows:

----------

using System.Reflection;

System.Type type = cityTextBox.GetType();

EventInfo eventInfo = type.GetEvent("TextChanged",
BindingFlags.Instance | BindingFlags.Public);

MethodInfo methodInfo = eventInfo.GetRaiseMethod(true);

//
// However, methodInfo always comes back null.
//
 
B

Berryl Hesh

Richard

Did you solve this?

Rhino has an event raiser that works well with interfaces only. It's hard to
believe that somebody doesn't have some sort of relection based tool you
could use to verify an event is wired or better yet, invoke it in a unit
test. I haven't found it yet though so wondering if you did.

Thanks,
Berryl


Nicholas Paldino said:
Richard,

You would have to use reflection for this, as you don't have access to
the event handler list from outside the instance that exposes the event.

You would have to look for the backing field for the delegate, but the
thing is, there is no guaranteed linking between that field and the event
exposed. For the standard event implementation (no add/remove handlers),
it should work, but you might run into some custom add/remove handlers and
it won't be that easy to figure out what the backing field for the event
is.

Are you doing this for unit testing, or within your app? If you are
doing it within your app, I would recommend making this a unit test or
maybe a custom rule for FxCop.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I have a huge Windows desktop application with over 100 individual
controls, like TextBox, NumericUpDown, ComboBox, etc.

I want each one to have its ValueChanged (or TextChanged) event
handler set, like:

-----------

System.Windows.Forms.TextBox cityTextBox;

cityTextBox = new TextBox();
cityTextBox.TextChanged += new EventHandler(cityTextBox_TextChanged);

-----------

I can loop through all of the controls of the application starting
with this.Controls and, recursively their children, finding everyone
of my 100 individual controls.

I want my software to verify if I have every TextChanged or
ValueChanged event handler set.

Any clues?

Thanks
 
R

richard.martino

Berryl:

No, I have not solved this.

I have this belief (from starting in assembler 30 years ago) that a
software engineer can write any software to do anything. Somehow the
C# language is lacking an EventInfo.GetValue() method, like
PropertyInfo.GetValue() and FieldInfo.GetValue().

The suggestion that (e-mail address removed) proposed seems to be written
in a language other than C#, and I could not port it over to C#
because some of the methods that he calls are not in C#.

I prefer to have my own software check for this rather than rely on an
external tool.

My overall goal is to verify that every user facing control has a
ValueChanged (or TextChanged) event handler defined. For the time
being, I will settle for my eyeballs and a good testing department.
 
B

Berryl Hesh

You could always do something like this, I suppose you know:
New Modified class ===========
public event EventHandler ValueChanged;
public bool ValueChangedIsWired() { return ValueChanged!= null; }
Test class ===========
foreach(var newClass in newClassCollection) {
if(!newClass.ValueChangedIsWired)
// throw exception, shoot somebody, etc.
}

I wonder why C# doesn't havesome EventInfo class though. The you could do
what you want without breaking encapsulation.

Good luck with it - BH


Berryl:

No, I have not solved this.

I have this belief (from starting in assembler 30 years ago) that a
software engineer can write any software to do anything. Somehow the
C# language is lacking an EventInfo.GetValue() method, like
PropertyInfo.GetValue() and FieldInfo.GetValue().

The suggestion that (e-mail address removed) proposed seems to be written
in a language other than C#, and I could not port it over to C#
because some of the methods that he calls are not in C#.

I prefer to have my own software check for this rather than rely on an
external tool.

My overall goal is to verify that every user facing control has a
ValueChanged (or TextChanged) event handler defined. For the time
being, I will settle for my eyeballs and a good testing department.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top