Estou me preparando para criar uma classe EventArgs genérica para argumentos de evento que carregam um único argumento:
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; }
}
}
Antes de fazer isso, o C # tem o mesmo recurso integrado à linguagem? Parece que me lembro de ter encontrado algo assim quando o C # 2.0 foi lançado, mas agora não consigo encontrar.
Ou, dito de outra forma, eu tenho que criar minha própria classe EventArgs genérica, ou o C # fornece uma? Obrigado pela ajuda.
Eventhandler<T>
EventArgs<T>
no código baseado em CAB / SCSF. É bastante comum em aplicativos CAB / SCSF. Embora não seja parte do quadro, não é um EventArgs <T> implementação.Respostas:
Não. Você provavelmente estava pensando em
EventHandler<T>
, o que permite definir o delegado para qualquer tipo específico de EventArgs.Eu pessoalmente não acho que
EventArgs<T>
seja um ajuste tão bom, no entanto. As informações usadas como uma "carga útil" nos argumentos de evento devem ser, em minha opinião, uma classe personalizada para tornar seu uso e propriedades esperadas muito claros. Usar uma classe genérica impedirá que você seja capaz de colocar nomes significativos no lugar. (O que "Dados" representam?)fonte
Devo dizer que não entendo todos os 'puristas' aqui. ou seja, se você já tem uma classe bag definida - que tem todas as especificações, propriedades etc. - por que o hack criou uma classe extra desnecessária apenas para poder seguir o mecanismo de evento / args, estilo de assinatura? coisa é - nem tudo que está em .NET - ou está 'faltando' - é 'bom' - MS tem se 'corrigido' por anos ... Eu diria apenas vá e crie um - como eu fiz - porque eu precisava desse jeito - e me economizou muito tempo,
fonte
Isso existe. Pelo menos agora.
Você pode encontrar
DataEventArgs<TData>
em alguns assemblies / namespaces diferentes da Microsoft, por exemplo, Microsoft.Practices.Prism.Events . No entanto, esses são namespaces que você pode não achar natural incluir em seu projeto, portanto, você pode usar apenas sua própria implementação.fonte
Caso você opte por não usar o Prism , mas ainda assim gostaria de tentar uma abordagem EventArgs genérica .
public class GenericEventArgs<T> : EventArgs { public T EventData { get; private set; } public GenericEventArgs(T EventData) { this.EventData = EventData; } }
// Use o seguinte código de exemplo para declarar evento ObjAdded
public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;
// Use o seguinte código de exemplo para gerar o evento ObjAdded
private void OnObjAdded(TargetObjType TargetObj) { if (ObjAdded!= null) { ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj)); } }
// E finalmente você pode inscrever seu evento ObjAdded
SubscriberObj.ObjAdded += (object sender, GenericEventArgs<TargetObjType> e) => { // Here you can explore your e.EventData properties };
fonte
NÃO HÁ ARGS GENÉRICAS INCORPORADAS. Se você seguir o padrão Microsoft EventHandler, então você implementar suas EventArgs derivados como você sugeriu:
public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }
.NO ENTANTO - se o guia de estilo da sua equipe aceitar uma simplificação - seu projeto pode usar eventos leves, como este:
public event Action<object, string> MyStringChanged;
uso:
// 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);
Normalmente, os projetos PoC usam a última abordagem. Em aplicativos profissionais, no entanto, esteja ciente da justificativa do policial FX # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx
fonte
O problema com um tipo genérico é que, mesmo se DerivedType herdar de BaseType, EventArgs (DerivedType) não herdará de EventArgs (BaseType). Usar EventArgs (BaseType) evitaria, portanto, o uso posterior de uma versão derivada do tipo.
fonte
IEventArgs
, mas as únicas classes que podem ser genéricas em relação aos parâmetros de tipo genérico são delegados que não serão alimentadosDelegate.Combine
. Os delegados que serão usados comDelegate.Combine
não devem ser covariantes, já que se pode armazenar, por exemplo, umAction<DerivedType>
em um campo do tipoAction<BaseType>
, mas uma tentativa posteriorCombine
com uma instância deAction<BaseType>
falhará.A razão de isso não existir é porque o que acabaria acontecendo é que você implementasse isso e, em seguida, quando for preencher o T, você deve criar uma classe com propriedades inequívocas fortemente tipadas que atua como o saco de dados para o argumento do seu evento, mas no meio da implementação, você percebe que não há razão para não fazer essa classe herdar de EventArgs e chamá-la de boa.
A menos que você queira apenas uma string ou algo similarmente básico para o seu saco de dados, nesse caso provavelmente existem classes EventArgs padrão no .NET destinadas a servir a qualquer propósito simples que você esteja buscando.
fonte