Pregunta

Estoy tratando de escribir en una API y necesito llamar a un controlador de eventos cuando obtengo datos de una tabla. Algo como esto:

    public override bool Run(Company.API api)
    {
        SomeInfo _someInfo = new SomeInfo();

        if (_someInfo.Results == 1)
            return true;
        else
            return false;

        using (MyTable table = new MyTable(api))
        {
            table.WhenData += new EventHandler<DataEventArgs<Record>>(table_WhenData);
            table.WhenDead += new EventHandler<EventArgs>(table_WhenDead);
            table.Start();
        }

    public void table_WhenData(object sender, DataEventArgs<Record> e)
    {
        return true;
    }

El problema que tengo es que no sé cómo pasar un valor de retorno de table_WhenData al método Run.

He intentado de muchas maneras (como intentar pasar _someInfo al método) pero parece que no puedo entender la sintaxis correcta.

Cualquier sugerencia es muy apreciada.

¿Fue útil?

Solución

El patrón común aquí no es devolver ningún dato del controlador de eventos, sino agregar propiedades a su objeto de argumento de evento para que el consumidor del evento pueda establecer las propiedades a las que puede acceder el llamador. Esto es muy común en el código de manejo de la interfaz de usuario; ves el concepto de evento Cancelar por todas partes.

Lo siguiente es un pseudocódigo y no está listo para compilar. Su intención es mostrar el patrón.

public MyEventArgs : EventArgs
{
   public bool Cancel{get;set;}
}

public bool fireEvent()
{
    MyEventArgs e=new MyEventArgs();

    //Don't forget a null check, assume this is an event
    FireEventHandler(this,e);

    return e.Cancel;
}

public HandleFireEvent(object sender, MyEventArgs e)
{
 e.Cancel=true;
}

Editar

Me gusta cómo Jon Skeet redactó esto: hacer que el EventArgs sea invaluable. Es decir, el consumidor del evento puede modificar el estado del objeto EventArgs , lo que permite que el generador del evento llegue a esos datos.

Otros consejos

Sé que esta es una publicación antigua, pero en caso de que alguien la encuentre, ciertamente es posible hacer esto. Usted declara su propio delegado que devuelve un valor, luego basa el evento en este nuevo delegado. Aquí hay un ejemplo:

En el declarante / editor del evento:

// the delegate
public delegate string ReturnStringEventHandler(object sender, EventArgs args);
// the event
public event ReturnStringEventHandler StringReturnEvent;
// raise the event
protected void OnStringReturnEvent(EventArgs e)
    {
        if (StringReturnEvent != null)  // make sure at least one subscriber
              // note the event is returning a string
              string myString = StringReturnEvent(this, e);
    }

En el evento suscriptor:

// Subscribe to event, probably in class constructor / initializer method
StringReturnEvent += HandleStringReturnEvent;

// Handle event, return data
private string HandleStringReturnEvent(object sender, EventArgs e)
{
    return "a string to return";
}

.NET proporciona un ejemplo de esto en el evento AssemblyResolve, que utiliza el delegado ResolveEventHandler para devolver datos, en este caso una referencia al ensamblaje deseado. Artículo de MSDN sobre el evento AssemblyResolve

Personalmente he usado tanto el evento AssemblyResolve como la técnica de delegado personalizado para devolver datos de un evento, y ambos funcionan como se esperaba en Visual Studio 2010.

La única forma de hacerlo es hacer que uno de los argumentos (preferiblemente los "argumentos" en lugar del remitente) sea mutable. Si aún no es mutable, básicamente tiene problemas, simplemente no hay forma de obtener la información.

(Bien, hay una forma: puede mantener el argumento del evento en sí mismo inmutable, pero hacer que un miembro sea un método que termine llamando a un delegado registrado por el código que genera el evento en primer lugar. Pero eso es horrible ... .)

Una solución simple es usar un cierre:

public override bool Run() {
    SomeInfo someInfo = ...
    table.WhenData += (obj, args) => {
        someInfo.Return = something
    };
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top