C# przekazywanie dodatkowych parametrów do obsługi zdarzeń?

Powiedzmy, że chcę przekazać dodatkowe dane podczas przypisywania obsługi zdarzenia. Rozważmy następujący kod:

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}

W Jaki Sposób mogę wprowadzić someData do mojej metody evhandlera?

Author: Andy Hin, 2010-11-18

8 answers

private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}
 51
Author: spender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-18 14:38:07

Przechwycone zmienne:

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

public void evHandler(Object sender, string someData)
{
    // use someData here
}

Or (C # 2.0 alternative):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });
 18
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-18 14:37:30

Ciężko mi było rozgryźć powyższy przykład @ spender, zwłaszcza z: Object.assignHandler((sender) => evHandler(sender,someData));, ponieważ nie ma czegoś takiego jak Object.assignHandler w dosłownym znaczeniu. Więc zrobiłem trochę więcej Googling i znalazłem Ten przykład . Odpowiedź Petera Duniho była ta, która kliknęła mi w głowie (to nie jest moja praca):

Snip

Zwyczajowym podejściem jest użycie anonimowej metody z obsługą zdarzenia to ma twój zmodyfikowany podpis. Na przykład:

void Onbutton_click(object sender, EventArgs e, int i) { ... }

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

Oczywiście, nie musisz zdawać w 172, ani nawet robić trzeciego parametru int. :)

/snip

Używając tego przykładu udało mi się przekazać w dwóch niestandardowych obiektach ComboBoxItem do zdarzenia Timer.Elapsed używając notacji lambda:

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

A potem do niego:

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

To nie jest żaden nowy kod z powyższych przykładów, ale pokazuje, jak je interpretować. Mam nadzieję, że ktoś taki jak ja uważa to za Pouczające i użyteczne, więc nie spędzają godzin próbując zrozumieć tak jak ja.

Ten kod działa w moim projekcie (z wyjątkiem wyjątku non-thread-safe z obiektami ComboBoxItem, które nie wierzę, że zmieniają sposób działania przykładu). Właśnie to rozgryzam.

 15
Author: delliottg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 22:55:23

Możesz spróbować to zrobić:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}
 3
Author: Idan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 17:41:01

Cóż, najprostsza metoda aby someData stała się zmienną członkowską TAK:

public class MyClass
{
    private string _eventData;

    private void setup(string someData) 
    {
       _eventData = someData;
       Object.assignHandler(evHandler);
    }

    public void evHandler()
    {
        // do something with _eventData here
    }
}

Nie jestem pewien, czy to jest Najlepszy sposób, ale tak naprawdę zależy to od typu zdarzenia, obiektu itp.

 0
Author: CodingGorilla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-18 14:37:23

Można utworzyć własny obiekt o dodatkowych właściwościach na podstawie obiektu:

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

Jeśli dane nie powinny być już zmieniane po inicjalizacji, możesz również dodać własny konstruktor, na przykład.

 0
Author: Michael Geier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-21 10:53:25

Oto moje jednoliniowe rozwiązanie, które Przekazuje dodatkowe parametry do obsługi timera.

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));
}
 0
Author: Ramius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 05:57:57

Moje pytanie, które było podobne, zostało oznaczone jako DUPLIKAT, więc pomyślałem, że dodam tutaj odpowiedź, ponieważ nie pozwala mi na moje pytanie.

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);
        }
    }
 0
Author: user441521,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 21:20:41