Me gustaría generar un evento y notificar a los suscriptores existentes si existe alguno. Pero también espero que los nuevos suscriptores sean notificados de todos los eventos planteados hasta el momento tan pronto como se suscriban. ¿Es esto posible listo para usar o necesito implementar esa funcionalidad yo mismo? En este momento, mi código se ve así:

public delegate void GridCompiled(int gridsize);
public event GridCompiled OnGridCompiled;

ctor(){
    if (OnGridCompiled != null)
        OnGridCompiled(gridsize);
}

Si el evento tiene 0 suscriptores, no se generará y tampoco se generará para los suscriptores que se suscriban después de que se haya generado el evento.

En caso de que necesite implementarlo yo mismo, ¿cuáles son mis opciones?

c#
3
Dread Boy 1 ene. 2017 a las 10:43
Puede ser una exageración, pero Rx.Net proporciona un método Replay: introtorx.com/Content/v1.0.10621.0/…
 – 
haim770
1 ene. 2017 a las 10:51
5
Me parece que busca una cola de mensajes, no eventos.
 – 
Zohar Peled
1 ene. 2017 a las 10:54

1 respuesta

La mejor respuesta

No hay seguimiento de los eventos que generan, por lo que tendría que implementar la funcionalidad usted mismo. Necesitaría una lista para almacenar sus argumentos de eventos anteriores en orden y ejecutar los eventos relacionados cuando se agrega un nuevo detector de eventos:

class Example {
    private readonly List<GridCompiledEventArgs> m_previousEventArgs = new List<EventArgs>();
    private EventHandler<GridCompiledEventArgs> m_gridCompiled;

    public event EventHandler<GridCompiledEventArgs> GridCompiled {
        add {
            //Raise previous events for the caller
            foreach(GridCompiledEventArgs e in m_previousEventArgs) {
                value(this, e);
            }
            //Add the event handler
            m_gridCompiled += value;
        }
        remove {
            m_gridCompiled -= value;
        }
    }

    protected virtual void OnGridCompiled(GridCompiledEventArgs e) {
        if (m_gridCompiled != null) {
            m_gridCompiled(this, e);
        }
        m_previousEventArgs.Add(e);
    }
}

Hay dos cosas que debe considerar para esta solución. Si desea abordarlos, su solución se volverá más compleja:

  1. Si un administrador de eventos puede cambiar GridCompiledEventArgs (por ejemplo, para devolver un estado a la persona que llama), los argumentos del evento se almacenarán en la lista de eventos anterior con esos cambios. Además, si un controlador de eventos mantiene una referencia a los argumentos del evento, incluso podría cambiarlo más tarde. Si no quiere eso, debe almacenar una copia en m_previousEventArgs y crear otra copia antes de generar el evento "histórico".
  2. Es una buena práctica permitir que las clases derivadas anulen el método OnGridCompiled en lugar de manejar el evento o cambiar su comportamiento. Si una clase derivada cambia OnGridCompiled para interceptar el evento y no generarlo en ciertos casos, este comportamiento no siempre se aplicará al evento "histórico", ya que se genera sin OnGridCompiled (que podría ser solo el comportamiento que desea). Si desea cambiar eso, debe implementar una solución que pase por OnGridCompiled. Si esta es una opción para usted, puede evitar este problema creando la clase sealed y el método OnGridCompiled private en lugar de protected virtual.
5
Sefe 1 ene. 2017 a las 21:04
Gracias. El punto 2 no se aplica a mi caso porque la clase ya está sellada, pero tendré que considerar el punto 1. Sin embargo, tengo una pregunta más. ¿Por qué no escribiste private event EventHandler<GridCompiledEventArgs> m_gridCompiled;?
 – 
Dread Boy
1 ene. 2017 a las 13:12
1
Porque no es un evento. GridCompiled es el evento. m_gridCompiled es solo el campo de respaldo que almacena el controlador de eventos. Toda la construcción se llama sintaxto del método de eventos .
 – 
Sefe
1 ene. 2017 a las 13:14
Quizás debería ampliar mi pregunta. Entiendo el evento como una lista de métodos que se llaman cuando se genera el evento y pensé que la palabra clave event es esencial para este comportamiento. Pero en el ejemplo anterior, puede agregar un controlador de eventos a m_gridCompiled (que no es un evento) y generarlo como lo haría con un evento. ¿La palabra clave event está ahí solo para aclarar el código?
 – 
Dread Boy
1 ene. 2017 a las 13:31
1
Un controlador de eventos es esencialmente un delegado. Los delegados se utilizan para muchos propósitos diferentes (eventos, devoluciones de llamada, etc.). Podría definir el evento con un delegado, pero eso provocaría una semántica diferente. Un evento tiene semántica de agregar / quitar. Eso significa que solo puede agregar o quitar controladores; otras operaciones (como asignaciones) no son posibles. Si no usa event, tiene semántica de campo / propiedad, que es diferente.
 – 
Sefe
1 ene. 2017 a las 14:36