2 votes

Récupération d'une méthode annotée à partir d'un constructeur d'attributs

Si j'annote une méthode d'une classe avec un attribut, je peux ensuite récupérer les attributs personnalisés de cette classe et voir si elle possède cet attribut ou non. Par exemple, je construis un programme orienté message et j'ai donc des classes comme

public class ErrorHandler
{
  [HandleMessage(ErrorHandling.ERROR)]
  private static void OnError(string message, object context, params object[] args)
  {
    Exception e;
    args.Extract(out e);

    Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
  }
}

Au moment de l'exécution, je peux le faire :

public static void RegisterStaticHandlers(Type type)
{
  foreach (var mInfo in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
  {
    var mAttr = mInfo.GetCustomAttribute<HandleMessageAttribute>();
    if (mAttr != null)
      RegisterInstanceHandler(mAttr.Message, mInfo.CreateDelegate<MessageHandler>());
  }
}

(J'ai quelques méthodes d'extension pour simplifier le code, elles ne sont pas pertinentes maintenant).

Ma question est la suivante : puis-je me débarrasser de ce RegisterStaticHandlers et enregistrer le gestionnaire dans le constructeur de l'attribut ?

public class HandleMessageAttribute : Attribute
{
  public string Message { get; private set; }

  public HandleMessageAttribute(string message)
  {
    Message = message;

    Messages.RegisterInstanceHandler(message, ... method reference here ...);
  }
}

Existe-t-il un moyen de récupérer la méthode qui est annotée par un attribut dans le constructeur d'attributs, au lieu de la manière opposée (et régulière) d'avoir la méthode et de récupérer ses attributs ?

[Edited] Je viens de réaliser que je peux au moins faire ça dans le constructeur statique :

static ErrorHandler()
{
  Messages.RegisterStaticHandlers(typeof(ErrorHandler));
}

Cela permet au moins de garder l'enregistrement d'une classe à l'intérieur de cette classe, ce qui est excellent en ce qui me concerne :)

3voto

Marc Gravell Points 482669

En bref, vous ne pouvez pas le faire à partir du constructeur de l'attribut. Lorsque l'attribut est construit, il n'a pas accès à la méthode/classe/champ/etc cible à laquelle il est appliqué.

D'après le code, je suppose que vous voulez que le code s'enregistre automatiquement au démarrage ? Une façon d'y parvenir pourrait être de sonder votre assemblage (une fois, au démarrage) - énumérer toutes les classes ( foreach(Type type in assembly) ), en trouvant ceux qui ont des gestionnaires d'erreurs candidats. Cela réduit la charge de la maintenance. Une autre option serait quelque chose de similaire en utilisant un fichier de configuration.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X