Adding Event to a Method - c#

I have a HTTP class that I've created, and I would to, if possible, attach a method each time either HTTP.post() or HTTP.get() is called. I'd like to be able to attach the event either before, or after.
I see this being done in a lot of Frameworks for the web, such as Wordpress and Symfony, but I'd like to do something similar on my WinForms app.
What design pattern am I looking for to achieve this so I can go and Google it.

You can create events on your objects and invoke them from anywhere in your code. I do this quite often.
public event EventHandler Getting;
public event EventHandler Setting;
void get()
{
if (Getting != null)
Getting.Invoke(this, EventArgs.Empty);
}
void post()
{
if (Setting != null)
Setting.Invoke(this, EventArgs.Empty);
}
Then other classes can handle these events something like this:
myHttp.Getting += myHttp_Getting;
public void myHttp_Getting(object sender, EventArgs e)
{
}
Edits:
You could also invoke the event like this:
void post()
{
if (Setting != null)
Setting(this, EventArgs.Empty);
}
You can only invoke an event from within its own class. This is not a problem because being able to do otherwise would cause really confusing code. Always check if it is null, because if there are no subscribers it will be null and will through a NullReferenceException when you invoke it.

Related

Is there a better way to initialize EventHandlers in C#

Let's say that I am writing a class library of some sort. I have a class:
public class PopupControl : UserControl {
// Some code
public event EventHandler PopupFinished;
}
If I want to handle this event in another class, I just use the += operator and nothing special happens. However, when the event is not handled anywhere, PopupFinished is null. And when I call PopupFinished (this, EventArgs.Empty), I get a NullReferenceException. So I need to do this:
public PopupControl () {
PopupFinished += popupFinished;
//Some more code
}
private void popupFinished (object sender, EventArgs e) {}
This doesn't sound like a good programming practice though. (or is it?)
Then I thought of another way:
try {
PopupFinished (this, EventArgs.Empty);
} catch (NullReferenceException) {}
But that doesn't sound right either.
Please tell me which of the above is better and whether there is another way to do that. Thanks!
Do a test to check PopupFinished is not null before calling it.
if(PopupFinished != null)
PopupFinished();

C# Delegate and Events for Beginners

I am a beginner C# programmer just stepping into the advanced world of plugins.
What I have at the moment: I have a base architecture for plugins to provide GUIs, Functions, and classes and each instance of GUI, function and class can be accessed by other plugins. (For ex. if the state of one plugin (plugin a) changes because the user has changed then it can change the text in a label in plugin b to the new user name).
What I am trying to get working: In one word. Events. If plugin a has an event I want plugin b to be able to subscribe to it. I am using a generic event handler delegate but it doesn't want to subscribe.
Resources I have seen already: http://www.dreamincode.net/forums/topic/78974-using-reflection-to-load-unreferenced-assemblies-at-runtime/ - Extremely useful
c# Plugin Event Handling
Firing events within a plug-in architecture vs single application
The issue is that most people are trying to subscribe to an event in a plugin from an application. I wish to subscribe one plugin to the event of a second plugin
My code at the moment:
Plugin 1 Events:
public class Events
{
public event tester testingevt;
public delegate void tester(object o, EventArgs e);
public void fireIt()
{
if (testingevt != null)
{
testingevt(this, null);
}
}
}
Plugin 2 (subscription):
public void onLoad()
{
object tempInstance = pf.getInstance("thisisaplugin", "Events");
Type t = tempInstance.GetType();
t.GetEvent("testingevt").AddEventHandler(tempInstance, new EventHandler(tester));
}
I have also seen various MSDN articles but none of them try to subscribe one plugin to another.
The code I am using came directly from the dreamincode.net link.
I have tried many different ways by creating delegate types, taking eventinfo variables to store the event and this was the closest I got to gathering it but the error this code throws is:
Object of type 'System.EventHandler' cannot be converted to type 'Test_Plugin_for_Server.Events+tester'
Please can anyone help me out?
Thanks in advance.
Your question is a bit vague, it seems that you want something like that
public class Events {
// Usually, you don't have to declare delegate:
// there's a special class for it - EventHandler or EventHandler<T>
public event EventHandler TestingEvt; // <- let's make it readable
public void fireIt() {
if (TestingEvt != null) {
// Passing null is a bad practice, give EventArgs.Empty instead
TestingEvt(this, EventArgs.Empty);
}
}
...
}
...
private void tester(Object sender, EventArgs e) {
// Events that fired the event - if you need it
Events caller = sender as Events;
...
}
...
public void onLoad() {
// Get the instance
Events tempInstance = pf.getInstance("thisisaplugin", "Events") as Events;
// Or just create an isntance
// Events tempInstance = new Events();
...
// Assigning (adding) the event
tempInstance.TestingEvt += tester;
...
}

Self-Testing delegates: avoid checking for null before invocation?

Is there any smart way to avoid the verbosity of testing the nullity on an event before calling it in a generic way ? It looks obvious that if I call a delegate, I want it to be assigned.
(If I Really want/need to test its nullity I could eventually do it explicitly, but putting this test systematically is kind of tedious and verbose.)
public delegate void ResetTradesDelegate();
public ResetTradesDelegate ResetTradesEvents;
public void OnSessionRxAdmMessage(IVfxFixAppSession session, FixMessage msg)
{
if (ResetTradesEvent != null) //<-- Is there "any" a way not to write this test explicitly for each delegate ?
ResetTradesEvent();
}
public event EventHandler NoDataEventHandler = delegate{};
Declaring an event in this way means it will never be null. It will always, at a minimum, have a single no-op event handler hooked up.
In your case, probably
public event ResetTradesDelegate ResetTradesEvents = delegate{};
Firing an event is always going to have a race condition associated with it. You're either going to risk trying to call a delegate when it's null, or calling a delegate after the event has been unhooked. Eric Lippert wrote a pretty comprehensive post on this topic here. The technique above still suffers from the second type of race condition, so the event handlers need to be robust to being called after the event has been unhooked.
static void CallIfNotNull(this Action action)
{
if (action != null) action();
}
As an extension method, this is quite convenient to use.
You can create your event-handler with an always-subscribed no-op event:
public class MyClass
{
public MyClass()
{
this.Event += (sender, e) => ();
}
public event EventHandler Event;
protected virtual void OnEvent()
{
this.Event(this, EventArgs.Empty);
}
}
However, this requires subscribing your event and will incur a performance penalty as the no-op delegate will still exist in the list of subscribed event handlers.
My preference here is to create a pair of extension methods to invoke any event handler, whilst performing a null-safe check:
public static void Raise(this EventHandler #event, object sender)
{
if(#event != null)
{
#event.Invoke(sender, EventArgs.Empty);
}
}
public static void Raise<TEventArgs>(
this EventHandler<TEventArgs> #event,
object sender,
TEventArgs args)
where TEventArgs : EventArgs
{
if(#event != null)
{
#event.Invoke(sender, args);
}
}
This can then be easily invoked anywhere in your library to safely raise the event:
this.ResetTradesEvent.Raise(this);
It's purely syntactic sugar; you're still doing the check on the delegate. It is however, a nice re-usable way to wrap up this smelly part of the C# language.
public static void Call(this Action action)
{
var safeAction = Interlocked.CompareExchange(ref action, null, null);
if (safeAction != null)
safeAction();
}
Using the null conditional operator keeps the test but is less verbose so works for me. I don't imagine it resolves the race condition that others have mentioned.
ResetTradesEvent?.Invoke();
This is suggested automatically in Visual Studio 2017.

Handling an event that might not have any subscriber

If a class fires events in its methods, the class does not have to know what or who subscribes its events. It is not also important if there is any subscriber.
In the code below, if there is not any subscriber to OnTrigger event, an exception occures.
public class EventTrigger
{
public static void Main(string[] args)
{
(new EventTrigger()).Trigger();
}
public delegate void Delegate1();
public event Delegate1 OnTrigger;
void Trigger()
{
OnTrigger();
}
}
I can call the event like this;
if (OnTrigger != null)
{
OnTrigger();
}
But it seems weird to me, because the triggerer does not have to know about subscription.
My question is:
Do I have to check if the event reference is null whenever I use it.
If you initialize OnTrigger then you wont have to do the check.
e.g.
public event Action OnTrigger = delegate { };
Yes ´delegate { }´ instantiates a new object, which is why this allows you to omit the ´null´ check.
´delegate { }´ returns nothing, so if you want it to return a string (which you need if Delegate1 returns a string) then you simply add ´return "";´ e.g.:
public event Action OnTrigger = delegate { return string.Empty; };
One I should add is that it's bad practice to do this in order to avoid a null check, as it's a lazy mans hack. Some code can still set the event to null, ´OnTrigger = null´ will break your code. And when it comes to (de)serialization it wont work at all.
The triggerer doesn't have to know about the individual subscribers, but it does need to know about subscription. You have to either do the null check every time or use the work-around Simon suggested.

Why must someone be subscribed for an event to occur?

Some text before the code so that the question summary isn't mangled.
class Tree
{
public event EventHandler MadeSound;
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
I haven't used events much in C#, but the fact that this would cause a NullRefEx seems weird. The EventHandler reference is considered null because it currently has no subsribers - but that doesn't mean that the event hasn't occurred, does it?
EventHandlers are differentiated from standard delegates by the event keyword. Why didn't the language designers set them up to fire silently in to the void when they have no subscribers? (I gather you can do this manually by explicitly adding an empty delegate).
Well, the canonical form is:
void OnMadeSound()
{
if (MadeSound != null)
{
MadeSound(this, new EventArgs());
}
}
public void Fall() { OnMadeSound(); }
which is very slightly faster that calling an empty delegate, so speed won out over programming convenience.
Another good way I've seen to get around this, without having to remember to check for null:
class Tree
{
public event EventHandler MadeSound = delegate {};
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
Note the anonymous delegate - probably a slight performance hit, so you have to figure out which method (check for null, or empty delegate) works best in your situation.
The recommended pattern is (.net 2.0+)
public class MyClass
{
public event EventHandler<EventArgs> MyEvent; // the event
// protected to allow subclasses to override what happens when event raised.
protected virtual void OnMyEvent(object sender, EventArgs e)
{
// prevent race condition by copying reference locally
EventHandler<EventArgs> localHandler = MyEvent;
if (localHandler != null)
{
localHandler(sender, e);
}
}
public void SomethingThatGeneratesEvent()
{
OnMyEvent(this, EventArgs.Empty);
}
}
I see a lot of recommendations for an empty delegate{} in an initializer, but I totally disagree with it. If you follow the above pattern you only check the event != null in one place. The empty delegate{} initializer is a waste because it's an extra call per event, it wastes memory, and it still can fail if MyEvent was set to null elsewhere in my class.
* If your class is sealed, you wouldn't make OnMyEvent() virtual.
You need to understand what your event declaration is actually doing. It's declaring both an event and a variable, When you refer to it within the class, you're just referring to the variable, which will be null when there are no subscribers.
Very Zen, eh?
You have to test for null when you want to raise an event:
protected void OnMyEvent()
{
if (this.MyEvent != null) this.MyEvent(this, EventArgs.Empty);
}
It would be nice if you didn't have to bother with this, but them's the breaks.
James provided a good technical reasoning, I would also like to add that I have seen people use this an advantage, if no subscribers are listening to an event, they will take action to log it in the code or something similar. A simpl example, but fitting in this context.
What is the point of raising an event if no one is listening? Technically, its just how C# chose to implement it.
In C#, an event is a delegate with some special feathers. A delegate in this case can be viewed as a linked list of function pointers (to handler methods of subscribers). When you 'fire the event' each function pointer is invoked in turn. Initially the delegate is a null object like anything else. When you do a += for the first subscribe action, Delegate.Combine is called which instantiates the list. (Calling null.Invoke() throws the null exception - when the event is fired.)
If you still feel that "it must not be", use a helper class EventsHelper as mentioned here with old and improved 'defensive event publishing' http://weblogs.asp.net/rosherove/articles/DefensiveEventPublishing.aspx
Using an extension method would be helpful in this scenario.
public static class EventExtension
{
public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs
{
if (handler != null)
{
handler(obj, args);
}
}
}
It can then be used like below.
public event EventHandler<YourEventArgs> YourEvent;
...
YourEvent.RaiseEvent(this, new YourEventArgs());
Thank you for the responses. I do understand why the NullReferenceException happens and how to get around it.
Gishu said
What is the point of raising an event if no one is listening?
Well, maybe it's a terminology thing. The appeal of an "event" system seems to me that all the responsibility of the fallout of the event that took place should be on the watchers and not the performer.
Perhaps a better thing to ask is: If a delegate field is declared with the event keyword in front of it, why doesn't the compiler translate all instances of:
MadeSound(this, EventArgs.Empty)
to
if (MadeSound != null) { MadeSound(this, EventArgs.Empty); }
behind the scenes in the same manner that other syntax shortcuts are? The number of boilerplate OnSomeEvent null checking methods that people have to write manually must be colossal.

Categories

Resources