Déclencher un événement d'une classe à partir d'une autre classe en C#
J'ai une classe, EventContainer.cs, qui contient un événement, dire:
public event EventHandler AfterSearch;
J'ai une autre classe, EventRaiser.cs. Comment puis-je augmenter (et pas de poignée) au-dessus dudit événement de cette classe?
Le soulevé de l'événement sera à son tour l'appel du gestionnaire de l'événement dans le EventContainer classe. Quelque chose comme ceci (ce n'est évidemment pas correct):
EventContainer obj = new EventContainer();
RaiseEvent(obj.AfterSearch);
- Cet ancien relais de poste soulève un problème qui peut facilement être contournée en utilisant un événement hub comme TinyMessenger.
Vous devez vous connecter pour publier un commentaire.
Ce n'est pas possible, les Événements ne peut être augmenté, passant à l'intérieur de la classe. Si vous pouviez le faire, il irait à l'encontre de l'objectif d'événements (être à la hauteur des changements d'état de l'intérieur de la classe). Je pense que vous êtes l'incompréhension de la fonction des événements un événement est définie à l'intérieur d'une classe et d'autres personnes pouvez vous abonner en faisant
obj.AfterSearch += handler;
(où le gestionnaire est une méthode selon la signature deAfterSearch
). On est capable de s'abonner à l'événement de l'extérieur, mais il ne peut être passé de l'intérieur de la classe qui la définit.static void Raise(this EventHandler ev) => if (ev != null) ev.BeginInvoke(..);
, C'est la méthode d'extension qui déclenche l'événement. Ce qui semble être "impossible" c'est d'obtenir leEventHandler
d'une autre classe.{void ButtonCustomHover(object sender, EventArgs e) { Button hoveredButton = sender as Button; hoveredButton.FlatAppearance.BorderColor = System.Drawing.Color.Orange; }
. C'est dans la classe de fenêtre maintenant, mais je veux l'extraire àUiExttectionClass
et de les utiliser dans d'autres classes. Direz-vous que j'aille mauvais sens?Il est POSSIBLE, mais à l'aide de piratage intelligent.
Inspiré par http://netpl.blogspot.com/2010/10/is-net-type-safe.html
Si vous ne croyez pas, essayez ce code.
On dirait que vous êtes à l'aide de la Modèle de délégué. Dans ce cas, le
AfterSearch
de l'événement doivent être définis sur laEventRaiser
de classe, et l'EventContainer
classe devraient consommer de l'événement:Dans EventRaiser.cs
Dans EventContainer.cs
Vous pouvez écrire une méthode publique de la classe, vous souhaitez que l'événement à feu et le feu de l'événement lorsqu'il est appelé. Vous pouvez ensuite appeler cette méthode à partir de n'importe quel utilisateur de votre classe.
Bien sûr, cela ruines d'encapsulation et est un mauvais design.
public static class
appeléGlobalEvents
qui vous pouvez vous adresser pour livrer des événements mondiaux aucun de la classe peut écouter. Le seul moyen actuellement pour ce faire est d'utiliserSystem.Action
. Le problème se pose quand je veux avoir des arguments nommés. Actuellement, il y a une balise XML résumé que vous pouvez remplir avec des arguments, mais il n'est toujours pas tout à fait aussi lisible et pas nativement pris en charge dans la plupart des IDEs' auto-résumé de la fonctionnalité.Il ya bonne façon de le faire. Chaque événement en C# dispose d'un délégué qui spécifie le signe de méthodes pour l'événement. Définir un champ dans votre classe externe avec le type de votre délégué d'événement. obtenir la référence de ce champ dans le constructeur de la classe externe et de l'enregistrer. Dans la classe principale de votre événement, envoyez la référence de l'événement pour le délégué de la classe externe. Maintenant, vous pouvez facilement appeler le délégué dans votre classe externe.
Pas une bonne programmation, mais si vous voulez le faire de toute façon, vous pouvez faire quelque chose comme ceci
D'accord avec Femaref -- et note ceci est une différence importante entre les délégués et les événements (voir, par exemple, cette entrée de blog pour une bonne discussion de ce et d'autres différences).
En fonction de ce que vous voulez atteindre, vous pourriez être mieux avec un délégué.
Je suis tombé sur ce problème, parce que je faisais des expériences avec l'appel de PropertyChanged événements de l'extérieur. Si vous n'avez pas à tout mettre en œuvre dans chaque classe. La solution de halorty ne fonctionne pas à l'aide des interfaces.
J'ai trouvé une solution de travail à l'aide de lourds réflexion. C'est sûrement lent et est la rupture du principe que les événements ne devrait être appelée à partir de l'intérieur de la classe. Mais il est intéressant de trouver une solution générique à ce problème....
Il fonctionne parce que chaque événement est une liste de méthodes d'appel a appelé.
Si nous pouvons obtenir la liste d'invocation et de l'appeler à chaque auditeur attaché à cet événement par notre propre.
Ici vous allez....
J'ai eu un genre de confusion et honnêtement, vous trouverez les réponses ici à être source de confusion. Bien qu'un couple fait allusion à des solutions que j'allais trouver serait de travailler.
Ma solution a été de frapper les livres et à devenir plus familier avec les représentants et les gestionnaires d'événements.
Bien que j'ai utilisé à la fois pour de nombreuses années, je n'ai jamais été intimement familier avec eux.
http://www.codeproject.com/Articles/20550/C-Event-Implementation-Fundamentals-Best-Practices
donne la meilleure explication de ces deux représentants et les gestionnaires d'événements que j'ai jamais lu et explique clairement qu'une classe peut être un éditeur d'événements et d'avoir d'autres catégories de les consommer.
Cet article: http://www.codeproject.com/Articles/12285/Implementing-an-event-which-supports-only-a-single explique comment une seule fonte des événements à un seul gestionnaire depuis les délégués sont multicast par définition . Un délégué hérite du système.MulticastDelegate la plupart, y compris le système des délégués sont Multicast.
J'ai trouvé que la multidiffusion signifiait que tout gestionnaire d'événements avec la même signature de recevoir le soulevé de l'événement. Multidiffusion le comportement m'a causé quelques nuits blanches que je passais à travers le code et vu mon cas apparemment à tort d'être envoyé aux gestionnaires que je n'avais pas l'intention d'obtenir cet événement. Les deux articles qui explique ce comportement.
Le deuxième article vous montre un chemin, et le premier article vous montre un autre, en faisant le délégué et la signature étroitement tapé.
Personnellement, je crois que le typage fort empêche stupide bugs qui peut être difficile à trouver. Donc j'aurais voter pour le premier article, même si j'ai reçu le deuxième article du code de travail. J'étais juste curieux. 🙂
Je suis aussi curieux de savoir si je pourrais obtenir de l' #2 articles du code de se comporter comme comment j'ai interprété la question initiale. Quelle que soit votre approche choisie ou si je suis aussi une mauvaise interprétation de la question d'origine, mon vrai message, c'est que je pense toujours que vous auriez avantage à lire le premier article que j'ai fait, surtout si les questions ou des réponses sur cette page vous laisser confondre. Si vous avez de la multidiffusion des cauchemars et ont besoin d'une solution rapide, puis l'article 2 peut vous aider.
J'ai commencé à jouer avec le deuxième article de la eventRaiser classe. J'ai fait un simple formulaire windows projet.
J'ai ajouté la deuxième articles de la classe EventRaiser.cs à mon projet.
Dans le formulaire Principal du code, j'ai défini une référence à cette EventRaiser classe au sommet comme
J'ai ajouté une méthode dans la principale forme de code que je voulais être appelée lorsque l'événement a été déclenché
puis dans le formulaire principal du constructeur, j'ai ajouté l'événement affectation:
Ensuite, j'ai créé une classe qui serait instancié par mon formulaire principal appelé "SimpleClass" par manque d'ingéniosité créatrice à l'heure actuelle.
Puis j'ai ajouté un bouton et dans l'événement click du bouton
J'ai instancié le SimpleClass code que j'ai voulu faire un événement à partir de:
Note l'instance de "eventRaiser" que j'ai passé à SimpleClass.cs. Qui a été définie et instancié plus tôt dans la Principale forme de code.
Dans le SimpleClass:
Le seul point à la méthode privée, j'ai appelé SimpleMethod était de vérifier qu'une entreprise privée dont l'étendue méthode pourrait encore augmenter l'événement, non pas que je doutais, mais je tiens à être positif.
J'ai couru le projet, ce qui a abouti dans la sensibilisation de l'événement de la "simpleMethod" de la "SimpleClass" jusqu'à la forme principale et allez la bonne méthode, appelée MainResponse prouvant qu'une classe peut en effet déclencher un événement qui est consommé par une autre classe.
Oui, l'événement doit être soulevé au sein de la classe qui a besoin de changer de diffusion à d'autres classes que les soins. La réception de classes peut être une classe ou de nombreuses de nombreuses classes en fonction de comment fortement typés vous les avez définies ou en les rendant unique jeté comme dans le 2ème article.
Espérons que cela aide et de ne pas brouiller l'eau. Personnellement, j'ai beaucoup de délégués et événements à nettoyer! Multidiffusion démons begone!
La collecte de classe a obtenir une nouvelle copie de la
EventHandler
.Une solution possible ci-dessous.
Exemple très simple. je tiens à le faire de cette façon en utilisant Gestionnaire.
J'ai pris une approche légèrement différente dans la résolution de ce problème. Ma solution a consisté en une winform avant la fin de, la Classe principale de la Bibliothèque (DLL) et à l'intérieur de cette dll, un secondaire de la classe ouvrière:
WinForm
|------> PickGen Bibliothèque
|---------> les Allocations de classe
Ce que j'ai décidé de le faire est de créer des événements dans le dll principale (PickGen) que les Attributions de la classe pourrait appeler, alors ces méthodes d'événement aurait appelé les événements de l'INTERFACE utilisateur.
Ainsi, les allocations déclenche un événement dans PickGen qui prend les valeurs de paramètre et soulève l'événement dans la forme. À partir d'un code de point de vue, c'est dans la plus basse classe:
puis plus tard dans la sous-classe code:
Dans le DLL principale de la bibliothèque de Classe, j'ai ces deux méthodes d'événement:
et je fais le lien ici quand j'ai créer la répartition de l'objet:
et je puis avoir des délégués qui sont mis en place pour lier la classe principale avec le winform code:
Il peut ne pas être la façon la plus élégante de le faire, mais en fin de compte, il ne fonctionne pas et sans être trop obscur.