Question

J'essaie d'écrire sur une API et j'ai besoin d'appeler un gestionnaire d'événements lorsque je récupère des données d'une table. Quelque chose comme ça:

    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;
    }

Le problème que je rencontre est que je ne sais pas comment renvoyer une valeur renvoyée de table_WhenData à la méthode Run.

J'ai essayé de nombreuses manières (comme essayer de passer _someInfo à la méthode), mais je n'arrive pas à obtenir la syntaxe correcte.

Toute suggestion est grandement appréciée.

Était-ce utile?

La solution

Le modèle courant ne consiste pas à renvoyer des données du gestionnaire d'événements, mais à ajouter des propriétés à votre objet d'argument d'événement afin que le consommateur de l'événement puisse définir les propriétés auxquelles l'appelant peut accéder. C'est très courant dans le code de gestion de l'interface utilisateur. vous voyez le concept d’annulation Annuler un peu partout.

Ce qui suit est du pseudo-code et n'est pas prêt à être compilé. Son intention est de montrer le motif.

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;
}

Modifier

J'aime la formulation de Jon Skeet: rendre les EventArgs mutageables. En d’autres termes, le consommateur de l’événement peut modifier l’état de l’objet EventArgs en permettant à l’éleveur de l’événement d’obtenir ces données.

Autres conseils

Je sais que ceci est un ancien post, mais au cas où quelqu'un le verrait bien, il est certainement possible de le faire. Vous déclarez votre propre délégué qui renvoie une valeur, puis basez l'événement sur ce nouveau délégué. Voici un exemple:

Dans le déclarant / éditeur de l'événement:

// 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);
    }

Dans l'abonné de l'événement:

// 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 en fournit un exemple dans l'événement AssemblyResolve, qui utilise le délégué ResolveEventHandler pour renvoyer des données, dans ce cas une référence à l'assembly souhaité. Article MSDN sur l'événement AssemblyResolve

J'ai personnellement utilisé l'événement AssemblyResolve et la technique de délégation personnalisée pour renvoyer les données d'un événement. Ils fonctionnent comme prévu dans Visual Studio 2010.

La seule façon de le faire est de rendre l’un des arguments (de préférence le "args" plutôt que l’expéditeur) mutable. Si ce n'est pas déjà mutable, vous avez essentiellement des problèmes - il n'y a aucun moyen de diffuser l'information.

(D'accord, il y a un moyen - vous pouvez garder l'argument d'événement lui-même immuable, mais en faire un membre d'une méthode qui finit par appeler un délégué enregistré par le code qui déclenche l'événement en premier lieu. Mais c'est horrible .. .)

Une solution simple consiste à utiliser une fermeture:

public override bool Run() {
    SomeInfo someInfo = ...
    table.WhenData += (obj, args) => {
        someInfo.Return = something
    };
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top