How do I pass objects in EventArgs

I personally like Toni Petrina's approach (see https://coderwall.com/p/wkzizq/generic-eventargs-class). It differs from the accepted answer in that you don't have to create a special EventHandler class (e.g. LoginCompletedEventArgs).

(Note: I am using VS 2015 and C# v6. In older versions of Visual Studio and C#, you may have to add using System.Linq;)

Create a generic EventArgs<T> class that inherits from EventArgs...

class EventArgs<T> : EventArgs {

  public T Value { get; private set; }

  public EventArgs(T val) {
     Value = val;
  }

}

Declare your event handler...

public event EventHandler<EventArgs<object>> LoginCompleted;

Assuming you have declared and assigned an object named loginObject, add code to raise you event...

private void RaiseLoginCompleted() {
  if (LoginCompleted != null)
    LoginCompleted(this, new EventArgs<object>(loginObject));
}

In your client code, add the LoginCompleted event handler (uses Linq and calls a local method)...

LoginCompleted += (o, e) => onLoginCompleted(e.Value); // calls a local method

void onLoginCompleted(LoginObject obj) {
  // add your code here
}

You would have to declare your event using EventHandler<T> where T is your class that derives from EventArgs:

public event EventHandler<LoginCompletedEventArgs> LoginCompleted;

LoginCompletedEventArgs could look like this:

public class LoginCompletedEventArgs : EventArgs
{
    private readonly YourBusinessObject _businessObject;

    public LoginCompletedEventArgs(YourBusinessObject businessObject)
    {
        _businessObject = businessObject;
    }

    public YourBusinessObject BusinessObject
    {
        get { return _businessObject; }
    }
}

Usage would be like this:

private void RaiseLoginCompleted(YourBusinessObject  businessObject)
{
    var handler = LoginCompleted;
    if(handler == null)
        return;

    handler(this, new LoginCompletedEventArgs(businessObject));
}

Please notice how I implemented RaiseLoginCompleted. This is a thread-safe version of raising the event. I eliminates a possible NullReferenceException that can occur in a race condition scenario where one thread wants to raise the event and another thread un-subscribes the last handler after the if check but before actually invoking the handler.


Well, you could do all that or you could define a delegate as your EventHandler and define your properties in its signature.

Such as:

public delegate void MyEventEventHandler(int prop1, string prop2, object prop3...);

public event MyEventEventHandler MyEvent;

I recommend use named tuples with EventHandler<TEventArgs>.

I like olddog's answer. Microsoft already has this delegate EventHandler< TEventArgs >.

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

You don't need to inherits from EventArgs.

Declare your event handler with named tuples.

public event EventHandler<(int id, string message, object LoginObject)> LoginCompleted;

In your client code, assign method to the LoginCompleted event handler

option 1: use lambda

LoginCompleted  += (o, e) =>
{
    Console.WriteLine($"Hello, sender is {o.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. ");
};

option 2: call a local method

LoginCompleted  += onLoginCompleted;

private static void onLoginCompleted  (object sender, (int id, string message,  object LoginObject) e)
{
    Console.WriteLine($"Hello, sender is {sender.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. ");
}

I just wrote an example, please refer to my repo

Tags:

C# 4.0