Я собираюсь создать общий класс EventArgs для аргументов событий, которые содержат один аргумент:
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; }
}
}
Прежде чем я это сделаю, есть ли в C # такая же функция, встроенная в язык? Я припоминаю, что сталкивался с чем-то подобным, когда вышел C # 2.0, но теперь я не могу его найти.
Или, другими словами, нужно ли мне создавать свой собственный общий класс EventArgs, или он есть в C #? Спасибо за вашу помощь.
Eventhandler<T>
EventArgs<T>
код на основе CAB / SCSF. Это довольно часто встречается в приложениях CAB / SCSF. Хотя это не входит в рамки, то есть Объект EventArgs <T> реализация.Ответы:
Нет. Вы, наверное, думали о том
EventHandler<T>
, что позволяет вам определять делегата для любого конкретного типа EventArgs.Лично я не считаю, что
EventArgs<T>
это так хорошо подходит. Информация, используемая в качестве «полезной нагрузки» в аргументах событий, должна, на мой взгляд, быть настраиваемым классом, чтобы сделать ее использование и ожидаемые свойства очень понятными. Использование универсального класса не позволит вам поставить на место значимые имена. (Что представляют собой «Данные»?)источник
Я должен сказать, что не понимаю всех здесь «пуристов». т.е. если у вас уже есть определенный класс сумки - который имеет все особенности, свойства и т. д. - почему хак создает один лишний ненужный класс, просто чтобы иметь возможность следовать механизму событий / аргументов, стилю подписи? Дело в том, что не все, что есть в .NET - или «отсутствует» в этом отношении - это «хорошо» - MS «исправляла» себя годами ... Я бы сказал, просто пойди и создай его - как я - потому что мне это было нужно именно так - и сэкономил мне много времени,
источник
Он существует. По крайней мере, сейчас.
Вы можете найти
DataEventArgs<TData>
в некоторых других сборках / пространствах имен Microsoft, например Microsoft.Practices.Prism.Events . Однако это пространства имен, которые вы не можете найти естественным для включения в свой проект, поэтому вы можете просто использовать свою собственную реализацию.источник
Если вы решили не использовать Prism , но все же хотели бы попробовать общий подход EventArgs .
public class GenericEventArgs<T> : EventArgs { public T EventData { get; private set; } public GenericEventArgs(T EventData) { this.EventData = EventData; } }
// Используйте следующий пример кода для объявления события ObjAdded
public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;
// Используйте следующий пример кода, чтобы вызвать событие ObjAdded
private void OnObjAdded(TargetObjType TargetObj) { if (ObjAdded!= null) { ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj)); } }
// И, наконец, вы можете подписаться на событие ObjAdded
SubscriberObj.ObjAdded += (object sender, GenericEventArgs<TargetObjType> e) => { // Here you can explore your e.EventData properties };
источник
НЕТ ВСТРОЕННЫХ ОБЩИХ АРГОВ. Если вы будете следовать Microsoft EventHandler шаблон, то вы реализуете ваши полученные EventArgs , как вы предложили:
public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }
.ОДНАКО - если ваше руководство по командному стилю допускает упрощение - ваш проект может использовать облегченные события, например:
public event Action<object, string> MyStringChanged;
Применение :
// 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);
Обычно в PoC-проектах используется второй подход. Однако в профессиональных приложениях следует помнить об оправдании FX Cop № CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx
источник
Проблема с универсальным типом заключается в том, что даже если DerivedType наследуется от BaseType, EventArgs (DerivedType) не будет наследовать от EventArgs (BaseType). Таким образом, использование EventArgs (BaseType) предотвратит последующее использование производной версии типа.
источник
IEventArgs
, но единственными классами, которые могут быть универсальными в отношении параметров универсального типа, являются делегаты, которым не будут передаваться данныеDelegate.Combine
. Делегаты, которые будут использоваться с,Delegate.Combine
не должны быть ковариантными, поскольку можно сохранить, например,Action<DerivedType>
в поле типаAction<BaseType>
, но более поздняя попытка сделатьCombine
это с экземпляромAction<BaseType>
не удастся.Причина, по которой этого не существует, заключается в том, что в конечном итоге вы реализуете это, а затем, когда вы перейдете к заполнению T, вы должны создать класс со строго типизированными однозначными свойствами, который действует как мешок данных для вашего аргумента события, но На полпути реализации вы понимаете, что нет причин, по которым вы просто не наследуете этот класс от EventArgs и не называете его хорошим.
Если вам просто не нужна строка или что-то подобное базовому для вашего пакета данных, в этом случае, вероятно, есть стандартные классы EventArgs в .NET, которые предназначены для выполнения любой простой цели, к которой вы стремитесь.
источник