Comment puis-je obtenir le membre auquel mon atsortingbut personnalisé a été appliqué?

Je crée un atsortingbut personnalisé en C # et je veux faire différentes choses selon que l’atsortingbut est appliqué à une méthode plutôt qu’à une propriété. Au début, j’allais faire un new StackTrace().GetFrame(1).GetMethod() dans mon constructeur d’atsortingbut personnalisé pour voir quelle méthode s’appelait le constructeur d’atsortingbut, mais maintenant je ne sais pas ce que cela me donnera. Que se passe-t-il si l’atsortingbut a été appliqué à une propriété? GetMethod() renverrait-il une instance MethodBase pour cette propriété? Existe-t-il une autre façon d’obtenir le membre auquel un atsortingbut a été appliqué en C #?

 [AtsortingbuteUsage(AtsortingbuteTargets.Method | AtsortingbuteTargets.Property, AllowMultiple = true)] public class MyCustomAtsortingbute : Atsortingbute 

Mise à jour: d’ accord, j’aurais peut-être posé la mauvaise question. À partir d’une classe d’atsortingbuts personnalisée, comment obtenir le membre (ou la classe contenant le membre) auquel mon atsortingbut personnalisé a été appliqué? Aaronaught a suggéré de ne pas remonter la stack pour trouver le membre de la classe auquel mon atsortingbut était appliqué, mais comment aurais-je pu obtenir cette information dans le constructeur de mon atsortingbut?

Comme il semble y avoir beaucoup de confusion en ce qui concerne le fonctionnement des frameworks et des méthodes de la stack, voici une démonstration simple:

 static void Main(ssortingng[] args) { MyClass c = new MyClass(); c.Name = "MyTest"; Console.ReadLine(); } class MyClass { private ssortingng name; void TestMethod() { StackTrace st = new StackTrace(); StackFrame currentFrame = st.GetFrame(1); MethodBase method = currentFrame.GetMethod(); Console.WriteLine(method.Name); } public ssortingng Name { get { return name; } set { TestMethod(); name = value; } } } 

Le résultat de ce programme sera:

set_Name

Les propriétés en C # sont une forme de sucre syntaxique. Ils se comstacknt en méthodes getter et setter dans le langage IL, et il est possible que certains langages .NET ne les reconnaissent même pas comme propriétés. La résolution des propriétés se fait entièrement par convention, il n’y a pas vraiment de règles dans la spécification IL.

Maintenant, disons pour le moment que vous avez une très bonne raison pour qu’un programme veuille examiner sa propre stack (et il y a peu de raisons pratiques de le faire). Pourquoi voulez-vous que le monde se comporte différemment pour les propriétés et les méthodes?

Toute la justification des atsortingbuts est qu’ils sont une sorte de métadonnées. Si vous voulez un comportement différent, codez-le dans l’atsortingbut . Si un atsortingbut peut signifier deux choses différentes selon qu’il est appliqué à une méthode ou à une propriété, vous devez avoir deux atsortingbuts . Définissez la cible sur AtsortingbuteTargets.Method et sur AtsortingbuteTargets.Property . Simple.

Mais encore une fois, marcher sur votre propre stack pour prendre des atsortingbuts de la méthode d’appel est au mieux dangereux. D’une certaine manière, vous gelez la conception de votre programme, ce qui complique considérablement la tâche de tout utilisateur. Ce n’est pas la façon dont les atsortingbuts sont normalement utilisés. Un exemple plus approprié serait quelque chose comme un atsortingbut de validation:

 public class Customer { [Required] public ssortingng Name { get; set; } } 

Ensuite, votre code de validation, qui ne sait rien de l’entité réelle transmise, peut le faire:

 public void Validate(object o) { Type t = o.GetType(); foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (Atsortingbute.IsDefined(prop, typeof(RequiredAtsortingbute))) { object value = prop.GetValue(o, null); if (value == null) throw new RequiredFieldException(prop.Name); } } } 

En d’autres termes, vous examinez les atsortingbuts d’une instance qui vous a été donnée mais que vous ne connaissez pas nécessairement sur le type de. Atsortingbuts XML, atsortingbuts de contrat de données, même atsortingbuts d’atsortingbut – presque tous les atsortingbuts du .NET Framework sont utilisés de cette manière, pour implémenter une fonctionnalité dynamic par rapport au type d’une instance, mais pas par rapport à l’ état du programme ou Que se passe-t-il sur la stack? Il est très improbable que vous maîsortingsiez cela au point où vous créez la trace de la stack.

Je vais donc recommander à nouveau que vous n’utilisiez pas la méthode de la marche à moins que vous ayez une très bonne raison de le faire, ce dont vous ne nous avez pas encore parlé. Sinon, vous risquez de vous retrouver dans un monde de souffrance.

Si vous devez absolument (ne dites pas que nous ne vous avons pas averti), utilisez deux atsortingbuts, l’un pouvant s’appliquer aux méthodes et l’autre aux propriétés. Je pense que vous trouverez que c’est beaucoup plus facile de travailler avec un seul super-atsortingbut.

Les atsortingbuts fournissent des métadonnées et ne savent rien de la chose (classe, membre, etc.) qu’ils décorent. D’autre part, la chose en cours de décoration peut demander les atsortingbuts avec lesquels elle est décorée.

Si vous devez connaître le type de l’object en cours de décoration, vous devrez le transmettre explicitement à votre atsortingbut dans son constructeur.

 [AtsortingbuteUsage(AtsortingbuteTargets.Method | AtsortingbuteTargets.Property, AllowMultiple = true)] public class MyCustomAtsortingbute : Atsortingbute { Type type; public MyCustomAtsortingbute(Type type) { this.type = type; } } 

Les atsortingbuts personnalisés sont activés par un code appelant la méthode GetCustomAtsortingbutes sur le ICustomAtsortingbuteProvider (object de reflection) qui représente l’emplacement auquel l’atsortingbut est appliqué. Ainsi, dans le cas d’une propriété, du code obtiendrait le PropertyInfo pour la propriété, puis appellerait GetCustomAtsortingbutes à ce sujet.

Si vous souhaitez créer un cadre de validation, vous devez écrire le code qui inspecte les types et les membres pour les atsortingbuts personnalisés. Vous pourriez par exemple avoir une interface que les atsortingbuts implémentent pour participer à votre cadre de validation. Pourrait être aussi simple que le suivant:

 public interface ICustomValidationAtsortingbute { void Attach(ICustomAtsortingbuteProvider foundOn); } 

Votre code pourrait chercher cette interface sur (par exemple) un Type:

 var validators = type.GetCustomAtsortingbutes(typeof(ICustomValidationAtsortingbute), true); foreach (ICustomValidationAtsortingbute validator in validators) { validator.Attach(type); } 

(vraisemblablement, vous parcourriez le graphe de reflection complet et faites ceci pour chaque ICustomAtsortingbuteProvider). Pour un exemple d’une approche similaire en action dans le .net FX, vous pouvez regarder les «comportements» de WCF (IServiceBehavior, IOperationBehavior, etc.).

Mise à jour: le .net FX a une sorte de cadre d’interception généraliste, mais essentiellement non documenté sous la forme de ContextBoundObject et ContextAtsortingbute. Vous pouvez rechercher sur le Web des exemples d’utilisation de l’AOP.

GetMethod vous renverra toujours le nom de la fonction. S’il s’agit d’une propriété, vous obtiendrez soit get_PropertyName ou set_PropertyName .

Une propriété est essentiellement un type de méthode. Ainsi, lorsque vous implémentez une propriété, le compilateur crée deux fonctions distinctes dans le MSIL résultant, une méthode get_ et une méthode set_. C’est pourquoi, dans la trace de la stack, vous recevez ces noms.