Question

Im trying to write to an API and I need to call an eventhandler when I get data from a table. Something like this:

    public override bool Run(Company.API api)
    {
        SomeInfo _someInfo = new SomeInfo();

        if (_someInfo.Results == 1)
            return true;
        else
            return false;

        using (MyTable table = new MyTable(api))
        {
            table.WhenData += new EventHandler<DataEventArgs<Record>>(table_WhenData);
            table.WhenDead += new EventHandler<EventArgs>(table_WhenDead);
            table.Start();
        }

    public void table_WhenData(object sender, DataEventArgs<Record> e)
    {
        return true;
    }

The problem that Im having is I dont know how to pass a return value back from table_WhenData to the Run method.

Ive tried many ways (like trying to pass _someInfo to the method) but I just cant seem to get the syntax right.

Any suggestion is greatly appreciated.

Was it helpful?

Solution

The common pattern here is not to return any data from the event handler, but to add properties to your event argument object so that the consumer of the event can set the properties which the caller can then access. This is very common in UI handling code; you see the Cancel event concept all over the place.

The following is pseudo code, and not compile ready. Its intent is to show the pattern.

public MyEventArgs : EventArgs
{
   public bool Cancel{get;set;}
}

public bool fireEvent()
{
    MyEventArgs e=new MyEventArgs();

    //Don't forget a null check, assume this is an event
    FireEventHandler(this,e);

    return e.Cancel;
}

public HandleFireEvent(object sender, MyEventArgs e)
{
 e.Cancel=true;
}

Edit

I like how Jon Skeet worded this: make the EventArgs mutuable. That is, the consumer of the event can modify the state of the EventArgs object allowing for the raiser of the event to get to that data.

OTHER TIPS

I know this is an old post, but just in case anyone comes across it, it is certainly possible to do this. You declare your own delegate that returns a value, then base the event off this new delegate. Here is an example:

In the event declarer / publisher:

// the delegate
public delegate string ReturnStringEventHandler(object sender, EventArgs args);
// the event
public event ReturnStringEventHandler StringReturnEvent;
// raise the event
protected void OnStringReturnEvent(EventArgs e)
    {
        if (StringReturnEvent != null)  // make sure at least one subscriber
              // note the event is returning a string
              string myString = StringReturnEvent(this, e);
    }

In the event subscriber:

// Subscribe to event, probably in class constructor / initializer method
StringReturnEvent += HandleStringReturnEvent;

// Handle event, return data
private string HandleStringReturnEvent(object sender, EventArgs e)
{
    return "a string to return";
}

.NET provides an example of this in the AssemblyResolve event, which uses the ResolveEventHandler delegate to return data, in this case a reference to the desired Assembly. MSDN Article on AssemblyResolve event

I have personally used both the AssemblyResolve event and the custom delegate technique to return data from an event, and they both work as expected on Visual Studio 2010.

The only way you can do it is to make one of the arguments (preferably the "args" rather than the sender) mutable. If it's not already mutable, you've basically got problems - there's just no way of getting the information out.

(Okay, there's one way - you can keep the event argument itself immutable, but make one member of it a method which ends up calling a delegate registered by the code raising the event in the first place. But that's horrible...)

A simple solution is to use a closure:

public override bool Run() {
    SomeInfo someInfo = ...
    table.WhenData += (obj, args) => {
        someInfo.Return = something
    };
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top