12
votes

Un auditeur d'événements peut-il être limité pour seulement avoir un abonné?

est-il possible d'empêcher de multiples abonnés de s'abonner à un événement?

J'ai créé un extrémité d'exemple rapide pour donner à ma question un contexte, mais malheureusement, je ne peux malheureusement pas la tester maintenant parce que je ne suis pas à mon vs machine. P>

L'objectif est de: P>

  • retourne une liste vide s'il n'y a pas d'abonnés. li>
  • renvoie la valeur de retour d'un seul abonné. li>
  • lancer une exception si plus d'un abonné tente de s'abonner à l'événement ( c'est le coquelicot de la question em>). li> ul>

    est-ce possible? p>

    public delegate List<IBaseWindow> GetWindowListDelegate();
    public static event GetWindowListDelegate GetWindowListEvent;
    
    public List<IBaseWindow> GetWindowList() {
    
        if (GetWindowListEvent == null) {
            return new List<IBaseWindow>();
        }
    
        return GetWindowListEvent();
     }
    


0 commentaires

5 Réponses :


10
votes

Vous pouvez utiliser Accessoires d'événement pour y parvenir. Quelque chose comme ce qui suit: xxx

Comme Andrew souligne, vous n'avez pas vraiment besoin d'événements pour y accomplir. Y a-t-il une raison particulière dont vous avez besoin?


3 commentaires

+1 comme une réponse. J'ajouterais pour faire attention à cette technique - quand un développeur .NET voit un type déclarer un événement, la Safe hypothèse (donc sans danger qu'il n'y a même pas une raison de vérifier autrement) est que de nouveaux auditeurs peuvent être ajouté sans problèmes.


Il n'y a pas de raison autre que mon "cadre métallique ne vue pas une alternative". J'ai demandé à Andrew de donner un exemple pendant que je vais lire des délégués et comment les utiliser sans événements. Désolé si cet écart de ma connaissance a créé une question folle! : |


@CuriousCoder: C'est ce que c'est tout à propos de; fermer ces lacunes.



16
votes

On dirait que vous n'avez pas besoin d'un événement - il suffit d'exposer le délégué lui-même et d'autoriser les appelants à définir la référence de délégué par leur propre.


6 commentaires

Désolé mais je ne comprends pas assez bien les délégués à savoir ce que vous voulez dire ... Ma compréhension des délégués est limitée à leur utilisation avec des événements. Peut-être que cela a limité comment je m'approche ce problème. Pourriez-vous donner un exemple pendant que je vais lire des délégués?


Il n'y a rien de difficile à comprendre, supprimez simplement le mot-clé event et "S'abonner" avec = au lieu de + = =


AFAIK Tous les délégués à .NET sont par défaut des délégués multi-Cast, c'est-à-dire qu'ils peuvent avoir plusieurs "abonnés".


Merci pour la clarification Thomas ... a du sens pour moi maintenant. Transfert de connaissances impressionnant dans 1 phrase! :RÉ


Ceci est trop tard, je ne sais pas si les choses changent depuis que la réponse est affichée, mais la modification de l'événement de délégué le rendrait vulnérable en laissant d'autres classes à l'invoquer. Comment réaliser un mécanisme d'abonnement unique sans laisser d'autres classes déclencher l'événement?


@Umairm peut-être un ensemble public de getter privé?



0
votes

Il est certainement possible de réaliser ce que vous voulez faire, mais cela ne se conforme pas à la convention - je vous exhorte à proposer une solution différente qui n'implique pas d'événements.

Comme expliqué par Jon Skeet , les événements publics sont des wrappers de type propriété autour d'un délégué de multidiffusion. P>

Vous pouvez penser à la mise en œuvre standard d'un événement en tant que liste de fonctions à appeler lorsque quelque chose se passe. p> xxx pré>

... Quand un développeur voit un tel événement, ils s'attendent à pouvoir y sous-traiter sans problème, comme un événement indique fondamentalement "tout nombre de types peut s'inscrire à Recevez cette notification d'événement ». P>

Il semble que vous souhaitiez permettre à quelqu'un de définir la mise en œuvre qui obtient la liste des fenêtres. Ce que je suggérerais de faire, c'est permettre aux gens de passer manuellement dans un délégué, puis détenus une instance Strong> Déléguate unique Strong>. Rendre explicite qu'il n'y a qu'un seul moyen de le définir; Si possible, je vous recommanderais d'utiliser l'injection de constructeur car cela supprime toute ambiguïté - vous ne pouvez définir que l'instance de déléguée une fois sur la construction, elle n'est plus modifiable par l'API publique (alors la classe B ne peut pas encombrer le délégué qui était déjà défini. par classe A). p>

EG P>

public class CallsDelegateToDoSomething
{      
   private Func<List<IBaseWindow>> m_windowLister; 

   public CallsDelegateToDoSomething(Func<List<IBaseWindow>> windowFunc)
   {
       m_windowLister = windowFunc;
   } 

   public List<IBaseWindow> GetWindowList() 
   {    
       if (windowLister == null) 
       {
           return new List<IBaseWindow>();
       }

       return m_windowLister();
   }
}


5 commentaires

Même un "délégué unique" peut entraîner l'invocation de plusieurs cibles.


Merci pour une réponse aussi complète et l'exemple final. Je regarde encore les délégués maintenant pour comprendre le commentaire de DTB.


DTB: Compte tenu de la liste d'invocation et de veiller à ce qu'il ait un compte de 1, existe-t-il un moyen élégant de veiller à ce qu'un délégué ne soit pas un délégué à plusieurs cases? Je travaille habituellement à l'aide d'interfaces pour ce type de chose (par exemple Iwindowster), de sorte que cela résout ce problème particulier, mais signifie que vous devez créer et mettre en œuvre une interface à la place, ce qui ne convient pas toujours.


Les délégués de l'OMI sont le mauvais outil pour obtenir ce que l'OP tente de réaliser - la question ressemble davantage à un cas de spécialisation. La meilleure solution serait probablement un objet implémentant une interface à transmettre ou de faire la classe abstraite et nécessitant des classes dérivées spécialisées qui remplissent les bits manquants. Mais puisque le code n'est qu'un exemple, il est difficile de dire. Deuxièmement, la déclaration qui restreignant les événements et les délégués célibataires à une cible unique n'est pas une bonne idée.


Yup, je suis d'accord avec tout ce que vous venez de dire.



7
votes

Juste pour compléter la réponse de John, voici une mise en œuvre de l'événement qui n'autorise qu'un gestionnaire: xxx

note que l'exposition d'un délégué plutôt que d'un événement n'empêche pas plusieurs gestionnaires: puisque .NET Les délégués sont multidiffuseurs, un délégué peut représenter un appel à plusieurs méthodes. Vous pouvez toutefois exposer le délégué comme une propriété et effectuer dans le Setter le même chèque que dans le code ci-dessus.

Quoi qu'il en soit, comme d'autres l'ont souligné, ce n'est probablement pas une bonne idée d'empêcher plusieurs gestionnaires de Un événement ... ce serait très déroutant de développer les développeurs qui l'utilisent.


1 commentaires

Merci d'avoir pris le temps supplémentaire pour fournir des informations supplémentaires. Je suis définitivement de l'esprit fixé maintenant que la conception initiale était fausse.



2
votes

Avec ce code, vous exposez votre délégué YeNamere, mais il désactivera la fonctionnalité + = = =. xxx

espère que cela aide.


0 commentaires