通过EventHandler传回返回值

时间:2009-09-18 18:43:10

标签: c# return-value event-handling

我试图写入API,我需要在从表中获取数据时调用eventhandler。像这样:

    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;
    }

我遇到的问题是我不知道如何将返回值从table_WhenData传递回Run方法。

我尝试了很多方法(比如尝试将_someInfo传递给方法),但我似乎无法使语法正确。

非常感谢任何建议。

4 个答案:

答案 0 :(得分:46)

这里的常见模式不是从事件处理程序返回任何数据,而是向事件参数对象添加属性,以便事件的使用者可以设置调用者随后可以访问的属性。这在UI处理代码中非常常见;你会看到所有地方的取消事件概念。

以下是伪代码,而不是编译就绪。它的目的是展示模式。

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;
}

修改

我喜欢Jon Skeet如何措辞:让EventArgs可变。也就是说,事件的使用者可以修改EventArgs对象的状态,从而允许事件的提升者获取该数据。

答案 1 :(得分:24)

我知道这是一个老帖子,但万一有人碰到它,肯定可以做到这一点。您声明自己的委托,它返回一个值,然后将该事件基于此新委托。这是一个例子:

在事件声明者/出版商中:

// 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);
    }

如果订阅者:

// 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在AssemblyResolve事件中提供了一个示例,它使用ResolveEventHandler委托来返回数据,在这种情况下是对所需程序集的引用。 MSDN Article on AssemblyResolve event

我亲自使用AssemblyResolve事件和自定义委托技术从事件中返回数据,并且它们都在Visual Studio 2010上按预期工作。

答案 2 :(得分:18)

你能做到的唯一方法是使其中一个参数(最好是“args”而不是发送者)可变。如果它还不是可变的,你基本上就会遇到问题 - 没有办法把信息拿出来。

(好吧,有一种方法 - 你可以保持事件参数本身不可变,但是让它的一个成员成为一个方法,它最终会调用由代码注册的代理,从而首先引发事件。但这太可怕了...... 。)

答案 3 :(得分:1)

一个简单的解决方案是使用闭包:

public override bool Run() {
    SomeInfo someInfo = ...
    table.WhenData += (obj, args) => {
        someInfo.Return = something
    };
}