Question

J'ai un cas d'utilisation où je dois me désabonner pour un événement. Mais avant de me désabonner, je veux m'assurer que ce mec est vraiment accro à cet événement ou non.

Faites-moi savoir comment je peux y arriver?

Était-ce utile?

La solution

L'exemple de classe Publisher contient un événement Publier. La méthode IsRegistered interroge les gestionnaires d'événements attachés aux événements pour l'instance de classe donnée et renvoie true s'il existe au moins un gestionnaire d'événements enregistré / attaché par cette instance de classe. La méthode IsRegistered remplacée fait la même chose mais pour les types statiques.

Mettez ce code dans un projet d'application console et appuyez sur F5 pour déboguer, essayez-le.

internal class Publisher
{
    internal event EventHandler<EventArgs> Publish;

    internal bool IsRegistered(Type type)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == null & item.Method.DeclaringType == type select item).Count() > 0;

    }
    internal bool IsRegistered(object instance)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == instance select item).Count() > 0;
    }

    static int Main(string[] args)
    {
        Publisher p = new Publisher();
        //
        p.Publish += new EventHandler<EventArgs>(static_Publish);
        p.Publish += new EventHandler<EventArgs>(p.instance_Publish);            
        //
        Console.WriteLine("eventhandler static_Publish attach: {0}", p.IsRegistered(typeof(Program)));
        Console.WriteLine("eventhandler instance_Publish attach: {0}", p.IsRegistered(program));
        //
        return 0;
    }

    void instance_Publish(object sender, EventArgs e)
    {

    }
    static void static_Publish(object sender, EventArgs e)
    {

    }
}`

Autres conseils

De Microsoft :

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Format the string to send inside the CustomEventArgs parameter
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());

                // Use the () operator to raise the event.
                handler(this, e);
            }
        }

Vous recherchez la partie if (gestionnaire! = null) . C’est null s’il n’ya aucun abonné, non null s’il y a des abonnés.

En supposant un environnement pub / sub, appelez simplement provider.Unsubscribe (EventType, subscriber) et laissez le fournisseur déterminer si l'abonné est abonné ou non

Vous pouvez le faire de deux manières:

  1. Vous pouvez créer une nouvelle chaîne de délégués en supprimant le délégué qui se désabonne et en le comparant à celui que vous aviez avant de l'enregistrer. Si vous désabonnez d'un délégué auquel est inscrit, vous récupérerez une nouvelle chaîne de délégués sans ce délégué. Si vous essayez de désinscrire un délégué auquel n'a pas souscrit , vous obtiendrez la même chaîne que celle que vous aviez.
  2. Vous pouvez parcourir manuellement la chaîne de délégués pour voir si le délégué que vous souhaitez désabonner est présent. Cela peut être fait en utilisant les méthodes normales de Linq comme .Contains pour plus de simplicité.

Le premier cas peut ressembler au code ci-dessous. Cela créera une nouvelle chaîne de délégués dans une variable temporaire, avec le délégué que vous souhaitez supprimer, supprimez, puis comparez la chaîne temporaire à la chaîne existante. S'ils sont identiques, le délégué n'était pas présent.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }
    remove
    {
        EventHandler temp = _Changed - value;
        if (_Changed == null || temp == _Changed)
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed = temp;
    }
}

Le second, comme le code ci-dessous, permet de voir si le délégué que vous souhaitez annuler est présent dans la chaîne de délégués.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }

    remove
    {
        if (_Changed == null || !_Changed.GetInvocationList().Contains(value))
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed -= value;
    }
}

Notez que vous pouvez, si vous le souhaitez, utiliser un code similaire pour gérer le cas où un délégué est ajouté deux fois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top