假设我想在分配事件处理程序时传递一些额外的数据。请考虑以下代码:
private void setup(string someData)
{
Object.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
// need someData here!!!
}
我该如何将someData
传入我的evHandler
方法中?
假设我想在分配事件处理程序时传递一些额外的数据。请考虑以下代码:
private void setup(string someData)
{
Object.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
// need someData here!!!
}
我该如何将someData
传入我的evHandler
方法中?
private void setup(string someData)
{
Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
// need someData here!!!
}
我在理解@spender上面的例子时遇到了困难,特别是这句话:Object.assignHandler((sender) => evHandler(sender,someData));
因为没有类似于 Object.assignHandler
的东西。所以我进行了更多的谷歌搜索,并找到了这个示例。Peter Duniho的答案让我恍然大悟(这不是我的成果):
省略内容
通常的方法是使用一个匿名方法和一个具有修改后签名的事件处理程序。例如:
void Onbutton_click(object sender, EventArgs e, int i) { ... } button.Click += delegate(object sender, EventArgs e) { Onbutton_click(sender, e, 172); };
当然,你不必传入172,甚至可以将第三个参数设为int的任何值. :)
/snip
使用该示例,我能够使用lambda符号将两个自定义的
ComboBoxItem
对象传递给Timer.Elapsed
事件:
simulatorTimer.Elapsed += (sender, e) => onTimedEvent(sender, e, (ComboBoxItem) cbPressureSetting.SelectedItem, (ComboBoxItem) cbTemperatureSetting.SelectedItem);
然后进入它的处理程序:
static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature) { Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature); }
这不是以上示例中的新代码,但它演示了如何解释它们。希望像我这样的人会发现它有用,这样他们就不必像我一样花费数小时来理解这个概念。
这段代码在我的项目中有效(除了一个非线程安全的异常与
ComboBoxItem
对象相关,我认为这并不影响示例的工作原理)。我正在解决这个问题。
捕获变量:
private void setup(string someData)
{
Object.assignHandler((sender,args) => {
evHandler(sender, someData);
});
}
public void evHandler(Object sender, string someData)
{
// use someData here
}
或者(C# 2.0的替代方案):
Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
evHandler(sender, someData);
});
string yourObject;
theClassWithTheEvent.myEvent += (sender, model) =>
{
yourObject = "somthing";
}
由于我的类似问题被标记为重复,所以我想在这里添加一个答案,因为它不允许我在我的问题上进行回答。
class Program
{
delegate void ComponentEventHandler(params dynamic[] args);
event ComponentEventHandler onTest;
static void Main(string[] args)
{
Program prg = new Program();
// can be bound to event and called that way
prg.onTest += prg.Test;
prg.onTest.Invoke("What", 5, 12.0);
Console.ReadKey();
}
public void Test(params dynamic[] values)
{
// assign our params to variables
string name = values[0];
int age = values[1];
double value = values[2];
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(value);
}
}
这是我的一行代码解决方案,可以向计时器处理程序传递额外的参数。
private void OnFailed(uint errorCode, string message)
{
ThreadPoolTimer.CreateTimer((timer) => {
UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
}, System.TimeSpan.FromMilliseconds(100));
}
在我的同事友情帮助之前,我在互联网上搜索了很久,感觉自己很蠢。Brackets是EventHandler
的解决方案。
例如:
event EventHandler<(int, bool)> EventName;
然后使用以下代码进行获取:
private void Delegate_EventName(object sender, (int, bool) e)
你可以随后访问信息:
var temp = e.Item1;<br>
var temp2 = e.Item2;<br>
或者您可以按照参数的预期添加名称,并通过e
进行调用:
private void Delegate_EventName(object sender, (int num, bool val) e)
然后你可以访问这些信息:
var temp = e.num;
var temp2 = e.val;
这个解决方案提供了一种方法,可以在仍然允许取消订阅的情况下向事件处理程序传递额外的参数:
在我的示例的Subscribe()函数中,我创建了一个Action,它调用一个lambda函数,该函数为我的事件处理程序提供了事件参数和额外的参数。然后,我将此Action存储在字典中。当我想要取消订阅时,我可以使用存储的Actions来执行。
这很有效,我在取消订阅之前和之后读取了侦听器的长度,它确实减少了 - 您可以再次无问题地取消订阅。
public class Player
{
public Action<JumpInfo> OnJump;
}
public class PlayerJumpListener
{
public List<Player> MyPlayerList;
private Dictionary<Player, Action<JumpInfo>> _jumpActionsByPlayer = new Dictionary<Player, Action<JumpInfo>>();
private void Subscribe()
{
foreach (Player player in MyPlayerList)
{
Action<JumpInfo> playerJumpAction = (jumpInfo) => HandlePlayerJump(jumpInfo, player);
player.OnJump += playerJumpAction;
_jumpActionsByPlayer.Add(player, playerJumpAction);
}
}
private void Unsubscibe()
{
foreach (KeyValuePair<Player, Action<JumpInfo>> kvp in _jumpActionsByPlayer)
{
kvp.Key.OnJump -= kvp.Value;
}
}
private void HandlePlayerJump(JumpInfo jumpInfo, Player player)
{
// player jumped
}
}
嗯,最简单的方法是将someData
作为成员变量:
public class MyClass
{
private string _eventData;
private void setup(string someData)
{
_eventData = someData;
Object.assignHandler(evHandler);
}
public void evHandler()
{
// do something with _eventData here
}
}
我不确定那是最好的方法,但这真的取决于事件类型、对象等。
你可以基于Object创建一个具有额外属性的自定义对象:
class CustomObject : Object
{
public string SomeData;
}
private void setup(string someData)
{
CustomObject customObject = new CustomObject { SomeData = someData };
CustomObject.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
string someData = ((CustomObject)sender).SomeData;
}
如果在初始化之后数据不应再更改,您还可以添加自定义构造函数,例如。