C# 通过 EventHandler 传递返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1446256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pass a return value back through an EventHandler
提问by Leroy Jenkins
Im trying to write to an API and I need to call an eventhandler when I get data from a table. Something like this:
我正在尝试写入 API,当我从表中获取数据时,我需要调用一个事件处理程序。像这样的东西:
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.
我遇到的问题是我不知道如何将返回值从 table_WhenData 传递回 Run 方法。
Ive tried many ways (like trying to pass _someInfo to the method) but I just cant seem to get the syntax right.
我尝试了很多方法(比如尝试将 _someInfo 传递给方法),但我似乎无法正确使用语法。
Any suggestion is greatly appreciated.
任何建议都非常感谢。
采纳答案by JoshBerke
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.
这里的常见模式不是从事件处理程序返回任何数据,而是向事件参数对象添加属性,以便事件的使用者可以设置调用者可以访问的属性。这在 UI 处理代码中很常见;你到处都可以看到取消事件的概念。
The following is pseudo code, and not compile ready. Its intent is to show the pattern.
以下为伪代码,未编译就绪。它的意图是显示模式。
public class 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.
我喜欢 Jon Skeet 的措辞:使EventArgs
可变的。也就是说,事件的消费者可以修改EventArgs
对象的状态,从而允许事件的发起者获取该数据。
回答by Jon Skeet
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.
您可以做到的唯一方法是使参数之一(最好是“args”而不是发件人)可变。如果它不是可变的,那么您基本上就会遇到问题 - 只是无法获取信息。
(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...)
(好吧,有一种方法 - 您可以保持事件参数本身不可变,但让它的一个成员成为一个方法,该方法最终调用由引发事件的代码注册的委托。但这太可怕了......)
回答by Igor ostrovsky
A simple solution is to use a closure:
一个简单的解决方案是使用闭包:
public override bool Run() {
SomeInfo someInfo = ...
table.WhenData += (obj, args) => {
someInfo.Return = something
};
}
回答by AFischbein
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
.NET 在 AssemblyResolve 事件中提供了一个示例,它使用 ResolveEventHandler 委托返回数据,在这种情况下是对所需程序集的引用。关于 AssemblyResolve 事件的 MSDN 文章
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.
我个人使用了 AssemblyResolve 事件和自定义委托技术来从事件返回数据,并且它们都在 Visual Studio 2010 上按预期工作。