J'utilise une classe que je ne peux pas éditer, il possède une propriété (un booléen) dont il serait bien d'être informé lors de son changement, je ne peux pas modifier les propriétés Obtenir ou définir comme je importe la classe à partir d'un .dll (que je n'ai pas le code pour).
Comment créer un événement / une fonction tiré lorsque la propriété est modifiée? p>
supplémentaire b> >
Il n'est changé que dans sa propre classe, directement à la variable privée sous-jacente. P>
E.g. P>
8 Réponses :
Vous ne pouvez pas faire cela directement [comme le dit Jon Skeet], à moins que ce soit virtuel, vous êtes en mesure d'intercepter toutes les créations d'instance de la classe et qu'il n'y a pas de changement à un champ de support qui influence la «valeur» réelle de le propiet. p>
Le seul moyen de la force brute Ceci est d'utiliser mono.cecil ou MS CCI pour instrument le disposeur de prop transfert A LA Cette dimectrée sur Cecil . (Ou postSharp) p>
Cependant, cela ne passerait pas de modifications internes au champ de support (s'il y en a même une). (C'est pourquoi l'emballage ne fonctionnera probablement pas). P>
Mise à jour: Compte tenu de votre mise à jour que vous essayez certainement de piéger le changement de champ sous-jacent, le seul moyen de le faire est d'utiliser PS / CCI / Cecil et analyser le flux pour intercepter toutes les mises à jour sur le terrain. En bref, pas très réalisable. P>
Vous ne pouvez pas, fondamentalement ... pas sans utiliser quelque chose comme l'API de débogueur pour injecter le code à l'heure d'exécution et modifier l'IL de la bibliothèque d'origine (et je ne recommande pas de ces solutions; à part quoi que ce soit Cela peut violer la licence de la bibliothèque). P>
Fondamentalement si une propriété ne prend pas en charge la notification, elle ne prend pas en charge la notification. Vous devriez rechercher une autre façon d'aborder votre problème. (Sondage du travail, par exemple?) P>
Je pense que je vais devoir devoir descendre la route de vote, et non quelque chose que j'espérais, car les données peuvent être réduites pendant les timings de vote (je veux attraper les données avant qu'il ne soit utilisé par d'autres fonctionnalités)
Ou enveloppez la classe avec votre propre classe qui prend en charge l'inotify ou vos propres implémentations?
@Andy: Cela dépend. Si vous faites cela, vous ne pouvez pas utiliser la classe comme type d'origine, quels autres bits du code peuvent avoir besoin.
Vous devrez créer une classe qui envoie la classe dans la DLL, dans la propriété Setter, il suffit de soulever un événement à l'aide des méthodes normales. P>
Mais cela ne piètre pas les mises à jour internes que le composant fabrique, soit via son constructeur, soit des modifications directes à l'état interne que le p; ropget réfléchirait.
Vous pouvez essayer de le hériter et d'utiliser son enfant au lieu de cela. Remplacer le "Set" de la propriété pour que cela augmente l'événement. P>
Edit: ... seulement si la propriété est virtuelle dans la classe mère ... p>
Pourriez-vous hériter de la classe et cacher la propriété? Quelque chose comme ça ...
Identique à Stackoverflow .com / questions / 1238137 / ... . (Et la mise à jour de q signifie que cela ne fonctionne pas)
@THOMAS: Non, le mot-clé «Nouveau» modificateur ne nécessite que la base sera virtuelle.
Ok, désolé, je n'ai pas vu le «nouveau» ... Cependant, cela ne fonctionnera que si vous manipulez l'objet à travers une variable de type myClass. Si la variable est de type basseClass, la mise en œuvre de la base sera appelée, car la propriété n'est pas polymorphe
Ceci est la protection de la propriété, ne remplace pas :)
Sans doute, le seul moyen réel de le faire est de créer une sorte de composant "surveillant", exécuté dans un thread séparé, dont le travail consiste à lire la propriété à intervalles et à soulever un événement lorsque la valeur de la propriété change. Bien sûr, cette solution navigue dans les eaux troubles de la filetage et de la synchronisation.
sur l'hypothèse que votre application est unique sur cet objet, votre solution la plus propre consiste à effectuer des appels de méthode sur cet objet via un objet proxy. Il aurait le travail de vérifier l'état avant et après l'état de la propriété et de soulever un événement dans le cas qu'il a changé. P>
Voici un exemple simple de ce dont je parle: P> < PRE> XXX PRE>
Évidemment, vous pouvez construire ce modèle de proxy dans un objet approprié - il suffit de savoir que Tous les appels forts> doivent passer par le proxy pour que l'événement soit soulevé quand vous vous attendez à ce que ce soit. p> p>
+1 pour l'exemple complet (Tho the Op fait clairement clair qu'il veut le traiter comme une boîte noire, de sorte que la réponse n'est pas appropriée IMNSHO)
Comme mentionné précédemment, la méthode la plus directe (et qui nécessite le moindre modification du code) consiste à utiliser une bibliothèque AOP telle que postSharp. P>
Cependant, une solution peut être obtenue à l'aide de C # /. Net traditionnel en utilisant le Propriété de dépendance forte> motif , utilisée à travers WPF à un grand effet. Je suggère de lire ce problème et d'envisager de mettre en œuvre un tel système (ou au moins une version simplifiée de celui-ci) pour votre projet, si vous approvision. P>
Je pense que l'idée d'Alex d'une enveloppe est bonne, cependant, étant donné que la chose la plus importante pour vous est que vous sachiez que la valeur est modifiée avant utilisation em>, vous pouvez simplement déplacer la notification à le getter, contourner les inquiétudes du changement de valeur interne. De cette façon, vous obtenez quelque chose de similaire au sondage, mais fiable: class MyClass : BaseClass
{
//local value
private bool local;
//first access yet?
private bool accessed = false;
// Override base property.
public new bool MyProperty
{
get
{
if(!accessed)
{
// modify first-get case according to your taste, e.g.
local = base.MyProperty;
accessed = true;
RaiseMyPropertyChangedBeforeUseEvent();
}
else
{
if(local != base.MyProperty)
{
local = base.MyProperty;
RaiseMyPropertyChangedBeforeUseEvent();
}
}
return local;
}
set
{
base.MyProperty = value;
}
}
}