Il semble plus propre de déclarer un enregistreur et d'appeler LogManager.GetLogger
dans une classe de base afin que tous ceux qui héritent puissent l'utiliser. Cependant, sur le site log4net et sur d'autres blogs comme dans cet article de blog , il est indiqué qu'il est préférable de déclarer un enregistreur par classe, car:
Vous pouvez utiliser les enregistreurs de cette manière pour isoler les problèmes de journalisation parmi vos objets, et je vous le recommande tout à fait. Cela vous permettra de limiter et de diriger la sortie des journaux de chaque enregistreur à l'aide du mécanisme de configuration hiérarchique de log4net.
Est-ce que cela signifie que si je le mets en classe de base, cela fera de cet enregistreur un goulot d'étranglement?
Si oui, existe-t-il d'autres solutions ou dois-je simplement créer un enregistreur par classe?
Le message ne vous dit pas spécifiquement d'utiliser un journal différent dans chaque classe dérivée, mais plutôt un journal différent pour type de classe en général. Vous pouvez, mais vous n'êtes pas obligé d'utiliser une nouvelle instance de journal dans chaque classe dérivée.
Une façon de voir les choses est qu'il peut être déroutant d'avoir deux enregistreurs distincts instanciés en même temps (car celui de base existera toujours), en particulier si vous masquez celui de base en utilisant le même nom d'enregistreur. Vos méthodes de classe de base (non substituées) feront toujours référence à l'enregistreur statique de base, et celles qui sont remplacées en utiliseront un autre.
De plus, l'article instancie l'enregistreur comme ceci:
static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType );
alors qu'un moyen légèrement plus simple pourrait être d'utiliser:
static readonly ILog Log = LogManager.GetLogger(typeof(YourClass));
Tout d'abord, il est marqué readonly
, ce qui signifie que vous ne pourrez pas modifier le champ accidentellement, une fois initialisé. Et utiliser ce type fonctionnera de la même manière qu’en réflexion, mais un peu plus vite (résolu au moment de la compilation). Visual Studio mettra également à jour le nom de la classe automatiquement si vous choisissez de le renommer (sinon vous auriez utilisé la surcharge de chaîne).
La pratique courante consiste à avoir un enregistreur par classe, PAS une classe de base. De cette façon, vous pouvez activer/désactiver la journalisation par classe.
Je pourrais également suggérer d'utiliser Common Logging 2.0, http://netcommon.sourceforge.net/ .
Il existe diverses implémentations de journalisation pour .NET actuellement utilisées, log4net, journalisation de la bibliothèque d'entreprise, NLog, pour nommer les plus courantes. L’inconvénient d’avoir une implémentation différente est qu’ils ne partagent pas une interface commune et imposent donc une implémentation de journalisation particulière aux utilisateurs de votre bibliothèque.
La bibliothèque Common.Logging introduit une abstraction simple pour vous permettre de sélectionner une implémentation de journalisation spécifique au moment de l'exécution. Ainsi, vous pouvez différer la décision de la bibliothèque de journalisation à utiliser jusqu'au déploiement. Les adaptateurs sont utilisés pour connecter un système de journalisation particulier à Common.Logging.
La déclaration fournie ne fait pas référence à un goulot d'étranglement. Déclarer votre enregistreur dans une classe de base limite le contrôle que vous avez sur la journalisation dans les classes dérivées. Si les classes A et B dérivent de la même classe de base contenant le logger, vous êtes bloqué avec les mêmes paramètres de journalisation pour toutes les journalisations effectuées dans les classes A et B.
log4net vous permet de configurer vos enregistreurs en fonction de la classe ou de l'espace de nom pour lequel ils ont été créés, vous donnant ainsi un contrôle très strict de ce qui est enregistré. Par exemple, avoir un journal de classe A au niveau info et un journal de classe B au niveau débogage.
L'ajout d'une seule ligne de code à chaque classe dans laquelle vous souhaitez connecter des éléments ne représente qu'un fardeau minime pour la flexibilité qu'il procure.
J'utilise un dictionnaire statique dans la classe de base, saisi par le nom du type:
private static readonly Dictionary<string, ILog> _loggers = new Dictionary<string, ILog>();
Avec une méthode (sur la classe de base) pour renvoyer un enregistreur:
private ILog GetLogger(){
var tn = this.GetType().FullName;
if (!_loggers.ContainsKey(tn)) {
_loggers.Add(tn,LogManager.GetLogger(this.GetType()));
}
return _loggers[tn];
}
J'ai aussi les méthodes de journalisation sur la classe de base:
public void Log(string msg, params object[] args) {
GetLogger().InfoFormat(msg, args);
}
Je suppose que cela me permettrait de configurer la journalisation par type (bien que ce ne soit pas le cas) et que la méthode GetLogger pourrait être exposée à des classes dérivées afin qu'elles puissent effectuer leur propre journalisation.