C # passando parâmetros extras para um manipulador de events?

Vamos dizer, eu quero passar alguns dados extras ao atribuir um manipulador de events. Considere o seguinte código:

private void setup(string someData) { Object.assignHandler(evHandler); } public void evHandler(Object sender) { // need someData here!!! } 

Como eu poderia obter alguns dados no meu método evHandler?

 private void setup(string someData) { Object.assignHandler((sender) => evHandler(sender,someData)); } public void evHandler(Object sender, string someData) { // need someData here!!! } 

Variáveis ​​capturadas:

 private void setup(string someData) { Object.assignHandler((sender,args) => { evHandler(sender, someData); }); } public void evHandler(Object sender, string someData) { // use someData here } 

Ou (alternativa C # 2.0):

  Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) { evHandler(sender, someData); }); 

Eu tive dificuldade em descobrir o exemplo @ Object.assignHandler((sender) => evHandler(sender,someData)); acima, especialmente com: Object.assignHandler((sender) => evHandler(sender,someData)); porque não existe algo como Object.assignHandler no sentido literal. Então eu pesquisei um pouco mais e encontrei este exemplo . A resposta de Peter Duniho foi a que clicou na minha cabeça (este não é o meu trabalho):

recorte

A abordagem usual é usar um método anônimo com um manipulador de events que tenha sua assinatura modificada. Por exemplo:

 void Onbutton_click(object sender, EventArgs e, int i) { ... } button.Click += delegate(object sender, EventArgs e) { Onbutton_click(sender, e, 172); }; 

Claro, você não precisa passar em 172, ou mesmo fazer o terceiro parâmetro int. 🙂

/recorte

Usando esse exemplo, consegui passar dois objects ComboBoxItem personalizados para um evento Timer.Elapsed usando a notação lambda:

 simulatorTimer.Elapsed += (sender, e) => onTimedEvent(sender, e, (ComboBoxItem) cbPressureSetting.SelectedItem, (ComboBoxItem) cbTemperatureSetting.SelectedItem); 

e depois no manipulador:

 static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature) { Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature); } 

Este não é um código novo dos exemplos acima, mas demonstra como interpretá-los. Espero que alguém como eu ache instrutivo e útil para que eles não passem horas tentando entender o conceito como eu fiz.

Este código funciona no meu projeto (exceto por uma exceção não-thread-safe com os objects ComboBoxItem que eu não acredito que mudam como o exemplo funciona). Eu estou entendendo isso agora.

você pode tentar fazer isso:

 string yourObject; theClassWithTheEvent.myEvent += (sender, model) => { yourObject = "somthing"; } 

Bem, o id método mais simples para fazer someData uma variável de membro da seguinte forma:

 public class MyClass { private string _eventData; private void setup(string someData) { _eventData = someData; Object.assignHandler(evHandler); } public void evHandler() { // do something with _eventData here } } 

Não tenho certeza se essa é a melhor maneira de fazer isso, mas realmente depende do tipo de evento, do object etc.

Você pode criar um object personalizado com propriedades adicionais baseadas em 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; } 

Se os dados não devem mais ser alterados após a boot, você também pode adicionar um construtor personalizado, por exemplo.

Aqui está a minha solução de uma linha que passa parâmetros extras para um manipulador de timer.

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

Minha pergunta que foi semelhante foi marcada como uma duplicata, então pensei em adicionar uma resposta aqui, já que ela não me deixa responder à minha pergunta.

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