natknąłem sytuacji gdzie potrzebne do czynienia z Delegate
wewnętrznie ale chciałem rodzajowe ograniczenie. W szczególności chciałem dodać obsługę zdarzeń za pomocą refleksji, ale chciałem użyć ogólnego argumentu dla delegata. Poniższy kod nie działa, ponieważ „Handler” to typ zmiennej, a kompilator nie rzuci Handler
do Delegate
:
public void AddHandler<Handler>(Control c, string eventName, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, (Delegate) d);
}
Jednak można przekazać do funkcji, które wykonuje konwersję dla Ciebie. convert
zajmuje Handler
argument i zwraca Delegate
:
public void AddHandler<Handler>(Control c, string eventName,
Func<Delegate, Handler> convert, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, convert(d));
}
Teraz kompilator jest szczęśliwy. Wywołanie metody jest łatwe. Na przykład, dołączenie do wydarzenia KeyPress
na Windows Forms kontroli:
AddHandler<KeyEventHandler>(someControl,
"KeyPress",
(h) => (KeyEventHandler) h,
SomeControl_KeyPress);
gdzie SomeControl_KeyPress
jest celem zdarzenia. Kluczem jest konwerter lambda - nie działa, ale przekonuje kompilatora, któremu dałeś prawidłowego delegata.
(Rozpocznij 280Z28) @ Justin: Dlaczego nie użyć tego?
public void AddHandler<Handler>(Control c, string eventName, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, d as Delegate);
}
(End 280Z28)
+1 dla: 1) za pomocą konstruktora statycznego i 2) zawierającego szczegółowy komunikat z powodu dziwnych warunków debugowania otaczającego inicjowanie typu. –
@MarcGravell: Nie rzuca wyjątku w statycznym inicjalizatorze naruszającym 'CA1065: Nie zgłaszaj wyjątków w nieoczekiwanych lokalizacjach' ... Zawsze byłem przy założeniu, że powinieneś użyć niestandardowej reguły analizy kodu, aby znaleźć niewłaściwe zastosowania twojego klasa, która zazwyczaj nie jest dostępna w czasie wykonywania. –