How to raise custom event from a Static Class

C#asp.net

C# Problem Overview


I have a static class that I would like to raise an event as part of a try catch block within a static method of that class.

For example in this method I would like to raise a custom event in the catch.

public static void saveMyMessage(String message)
{
    try
    {
        //Do Database stuff
    }
    catch (Exception e)
        {
              //Raise custom event here
        }
}

Thank you.

C# Solutions


Solution 1 - C#

Important: be very careful about subscribing to a static event from instances. Static-to-static is fine, but a subscription from a static event to an instance handler is a great (read: very dangerous) way to keep that instance alive forever. GC will see the link, and will not collect the instance unless you unsubscribe (or use something like a WeakReference).

The pattern for creating static events is the same as instance events, just with static:

public static event EventHandler SomeEvent;

To make life easier (re null checking), a useful trick here is to add a trivial handler:

public static event EventHandler SomeEvent = delegate {};

Then you can simply invoke it without the null-check:

SomeEvent(null, EventArgs.Empty);

Note that because delegate instances are immutable, and de-referencing is thread-safe, there is never a race condition here, and no need to lock... who-ever is subscribed when we de-reference gets invoked.

(adjust for your own event-args etc). This trick applies equally to instance events.

Solution 2 - C#

Your event would also need to be static:

public class ErrorEventArgs : EventArgs
{
	private Exception error;
	private string message;
	
	public ErrorEventArgs(Exception ex, string msg)
	{
		error = ex;
		message = msg;
	}

	public Exception Error
	{
		get { return error; }
	}
	
	public string Message 
	{
		get { return message; }
	}
}

public static class Service
{
	public static EventHandler<ErrorEventArgs> OnError;
	
	public static void SaveMyMessage(String message)
	{
            EventHandler<ErrorEventArgs> errorEvent = OnError;
		if (errorEvent != null)
		{
			errorEvent(null, new ErrorEventArgs(null, message));
		}
	}
}

And Usage:

public class Test
{
   public void OnError(object sender, ErrorEventArgs args)
   {
    	Console.WriteLine(args.Message);
   }
 }

 Test t = new Test();
 Service.OnError += t.OnError;
 Service.SaveMyMessage("Test message");

Solution 3 - C#

Several folks have offered up code examples, just don't fire an event using code such as:

if(null != ExampleEvent)
{
  ExampleEvent(/* put parameters here, for events: sender, eventArgs */);
}

as this contains a race condition between when you check the event for null and when you actually fire the event. Instead use a simple variation:

MyEvent exampleEventCopy = ExampleEvent;
if(null != exampleEventCopy)
{
  exampleEventCopy(/* put parameters here, for events: sender, eventArgs */);
}

This will copy any event subscribers into the exampleEventCopy, which you can then use as a local-only version of the public event without having to worry about any race conditions (Essentially, it is possible that another thread could pre-empt you right after you have checked the public event for null and proceed to remove all subscribers from the event, causing the subsequent firing of the event to throw an exception, by using a local-only copy, you avoid the possibility of another thread removing subscribers, since there is no way they could access the local variable).

Solution 4 - C#

Note: VS2008, C#

Just declare an event as you normally would within the static class, but be sure to mark the event as static:

public static event EventHandler Work;

Then just subscribe to it as you normally would.

Solution 5 - C#

Just to add "Delegates are immutable" So, as shown in the example above the following line obtains a copy of the delegate.

EventHandler<ErrorEventArgs> errorEvent = OnError;

Solution 6 - C#

The way I did this is the following:

1- define a delegate (this will enable you to have customized arguments):

public delegate void CustomeEventHandler(string str);

2- define an event based on the previously defined delegate:

public static event CustomeEventHandler ReadLine;

3- create an event handler:

static void OnLineRead(string currentLine)
        {
            if (ReadLine != null)
                ReadLine(currentLine);
        }

4- raise your event using the event handler (just call it wherever you want the event to be raised).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAvitusView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#ToddView Answer on Stackoverflow
Solution 3 - C#Brian B.View Answer on Stackoverflow
Solution 4 - C#MikeView Answer on Stackoverflow
Solution 5 - C#Nelson P. VargheseView Answer on Stackoverflow
Solution 6 - C#HaniView Answer on Stackoverflow