Przygotowuję się do utworzenia ogólnej klasy EventArgs dla argumentów zdarzeń, które zawierają pojedynczy argument:
public class EventArg<T> : EventArgs
{
// Property variable
private readonly T p_EventData;
// Constructor
public EventArg(T data)
{
p_EventData = data;
}
// Property for EventArgs argument
public T Data
{
get { return p_EventData; }
}
}
Zanim to zrobię, czy C # ma tę samą funkcję wbudowaną w język? Wydaje mi się, że napotkałem coś takiego, gdy pojawił się C # 2.0, ale teraz nie mogę go znaleźć.
Albo inaczej, czy muszę utworzyć własną klasę ogólną EventArgs, czy też C # ją udostępnia? Dzięki za pomoc.
Eventhandler<T>
EventArgs<T>
w kodzie opartym na CAB / SCSF. Jest to dość powszechne w aplikacjach CAB / SCSF. Choć nie jest to częścią ram, tam jest an EventArgs <T> realizacja.Odpowiedzi:
Nie. Prawdopodobnie
EventHandler<T>
myślałeś o tym , co pozwala zdefiniować delegata dla dowolnego konkretnego typu EventArgs.Osobiście uważam jednak, że nie
EventArgs<T>
jest to tak dobre dopasowanie. Informacje używane jako „ładunek” w argumentach zdarzeń powinny być, moim zdaniem, niestandardową klasą, aby jej użycie i oczekiwane właściwości były bardzo jasne. Użycie klasy ogólnej uniemożliwi Ci wstawianie znaczących nazw w miejsce. (Co oznaczają „Dane”?)źródło
Muszę powiedzieć, że nie rozumiem tu wszystkich „purystów”. tzn. jeśli masz już zdefiniowaną klasę worka - która ma wszystkie szczegóły, właściwości itp. - dlaczego hack tworzy jedną dodatkową niepotrzebną klasę tylko po to, aby móc śledzić mechanizm zdarzeń / argumentów, styl sygnatury? rzecz w tym, że - nie wszystko, co jest w .NET - lub czego „brakuje” - jest „dobre” - MS „poprawia się” od lat ... Powiedziałbym, po prostu idź i stwórz taki - tak jak ja - bo tak właśnie tego potrzebowałem - i zaoszczędziłem dużo czasu,
źródło
Ona istnieje. Przynajmniej teraz.
Możesz znaleźć
DataEventArgs<TData>
w różnych zestawach / przestrzeniach nazw Microsoft , na przykład Microsoft.Practices.Prism.Events . Są to jednak przestrzenie nazw, których umieszczanie w projekcie może nie być naturalne, więc możesz po prostu użyć własnej implementacji.źródło
Jeśli zdecydujesz się nie używać Prism , ale nadal chciałbyś wypróbować ogólne podejście EventArgs .
public class GenericEventArgs<T> : EventArgs { public T EventData { get; private set; } public GenericEventArgs(T EventData) { this.EventData = EventData; } }
// Użyj następującego przykładowego kodu, aby zadeklarować zdarzenie ObjAdded
public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;
// Użyj następującego przykładowego kodu, aby zgłosić zdarzenie ObjAdded
private void OnObjAdded(TargetObjType TargetObj) { if (ObjAdded!= null) { ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj)); } }
// I na koniec możesz zasubskrybować swoje zdarzenie ObjAdded
SubscriberObj.ObjAdded += (object sender, GenericEventArgs<TargetObjType> e) => { // Here you can explore your e.EventData properties };
źródło
NIE MA WBUDOWANYCH OGÓLNYCH ARG. Jeśli zastosujemy Microsoft EventHandler wzór, a następnie wdrożyć swoje EventArgs wywodzące się jak sugeruje:
public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }
.JEDNAK - jeśli przewodnik stylu Twojego zespołu akceptuje uproszczenie - Twój projekt może korzystać z lekkich wydarzeń, takich jak to:
public event Action<object, string> MyStringChanged;
stosowanie :
// How to rise private void OnMyStringChanged(string e) { Action<object, string> handler = MyStringChanged; // thread safeness if (handler != null) { handler(this, e); } } // How to handle myObject.MyStringChanged += (sender, e) => Console.WriteLine(e);
Zwykle projekty PoC wykorzystują to drugie podejście. W profesjonalnych zastosowaniach należy jednak pamiętać o uzasadnieniu policjanta FX # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx
źródło
Problem z typem ogólnym polega na tym, że nawet jeśli DerivedType dziedziczy po BaseType, EventArgs (DerivedType) nie będzie dziedziczyć po EventArgs (BaseType). Użycie EventArgs (BaseType) uniemożliwiłoby w ten sposób późniejsze użycie pochodnej wersji typu.
źródło
IEventArgs
, ale jedynymi klasami, które mogą być generyczne w odniesieniu do parametrów typu ogólnego, są delegaci, do których nie będą przekazywaneDelegate.Combine
. Delegaty, które będą używane z,Delegate.Combine
nie powinny być kowariantne, ponieważ można zapisać np. AAction<DerivedType>
w polu typuAction<BaseType>
, ale późniejsza próba wykonaniaCombine
tego z instancjąAction<BaseType>
zakończy się niepowodzeniem.Powodem, dla którego to nie istnieje, jest to, że to, co by się stało, to zaimplementowanie tego, a następnie kiedy idziesz do wypełnienia T, powinieneś utworzyć klasę z silnie wpisanymi jednoznacznymi właściwościami, która działa jako zbiór danych dla twojego zdarzenia arg, ale w połowie implementacji zdajesz sobie sprawę, że nie ma powodu, dla którego nie chcesz po prostu dziedziczyć tej klasy po EventArgs i nazwać ją dobrą.
Chyba że potrzebujesz tylko ciągu znaków lub czegoś podobnie podstawowego dla swojego zbioru danych, w takim przypadku prawdopodobnie istnieją standardowe klasy EventArgs w .NET, które mają służyć dowolnemu prostemu celowi.
źródło