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