L'injection de dépendance et nommé bûcherons

Je suis intéressé à en apprendre davantage sur la façon dont les gens injecter de l'enregistrement à l'aide d'injection de dépendance des plates-formes. Bien que les liens ci-dessous et mes exemples se réfèrent à log4net et de l'Unité, je ne suis pas forcément d'utiliser l'un de ceux-ci. Pour l'injection de dépendances/CIO, je vais probablement l'utiliser MEF comme c'est la norme que le reste du projet (gros) est à régler sur.

Je suis très nouveau à l'injection de dépendances/cio et je suis assez novice en C# et .NET (ont écrit très peu de production de code en C#/.NET, après les 10 dernières années de VC6 et VB6). J'ai fait beaucoup de recherches sur les différentes solutions de connexion qui sont là-bas, donc je pense que j'ai une bonne maîtrise de leurs ensembles de fonctionnalités. Je ne suis pas assez familier avec le réel de la mécanique de l'obtention d'une dépendance à l'injection (ou, peut-être plus "correctement", d'obtenir une version abstraite de l'une dépendance injecté).

J'ai vu d'autres messages liés à l'exploitation forestière et/ou de l'injection de dépendances comme:
l'injection de dépendance et de journalisation des interfaces

La journalisation des meilleures pratiques

Que serait un Log4Net classe Wrapper ressembler?

de nouveau sur log4net et de l'Unité du CIO config

Ma question n'est pas spécialement à voir avec "Comment j'ai injecter de la plateforme d'enregistrement xxx à l'aide du cio outil yyy?" Je suis plutôt intéressé par la façon dont les gens ont géré emballage de la plateforme d'enregistrement (comme c'est souvent, mais pas toujours recommandé) et de configuration (c-app.config). Par exemple, à l'aide de log4net comme un exemple, j'ai pu configurer (dans l'app.config) un certain nombre de bûcherons, puis obtenir ces enregistreurs (sans injection de dépendance) dans le niveau moyen de l'aide d'un code comme ceci:

private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

Sinon, si mon enregistreur n'est pas nommé pour une classe, mais plutôt, pour un domaine fonctionnel, je pourrais faire ceci:

private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");

Donc, je suppose que mes "exigences" serait quelque chose comme ceci:

  1. Je voudrais isoler mon produit est source d'une dépendance directe sur une plateforme d'enregistrement.

  2. Je voudrais être en mesure de résoudre un spécifique nommé journal instance (probablement partage la même instance parmi tous les demandeurs de la même instance nommée), soit directement ou indirectement, par une sorte de l'injection de dépendance, probablement MEF.

  3. Je ne sais pas si je dirais que c'est un dur, mais je voudrais la possibilité d'obtenir un nommé enregistreur (différent de la classe logger) sur demande. Par exemple, je pourrais créer un historique de ma classe basée sur le nom de la classe, mais une méthode particulièrement lourd diagnostics que je voudrais contrôler séparément. En d'autres termes, j'aimerais une classe unique de "dépendre" sur deux enregistreur de cas.

Nous allons commencer avec le numéro 1. J'ai lu un certain nombre d'articles, principalement ici sur stackoverflow, quant à savoir si ou non il est une bonne idée d'envelopper. Voir les "meilleures pratiques" du lien ci-dessus et accédez à jeffrey hantins'commentaire pour un point de vue sur pourquoi c'est mauvais pour l'envelopper de log4net. Si vous n'avez wrap (et si vous pouvez rassembler efficacement) pourriez-vous envelopper strictement dans le but d'injection et/ou la suppression directe de depdency? Ou souhaitez-vous également tenter de faire abstraction de certains ou de tous les log4net app.les informations de configuration?

Disons que je veux utiliser le Système.Diagnostics, j'aurais probablement envie de mettre en œuvre une interface basée sur l'enregistreur (peut-être même à l'aide de la "commune" de ILogger/ILog interface), probablement basée sur TraceSource, pour que je puisse injecter. Souhaitez-vous mettre en œuvre l'interface, dire plus TraceSource, et il suffit d'utiliser le Système.Diagnostics app.les informations de configuration que c'est?

Quelque chose comme ceci:

public class MyLogger : ILogger
{
  private TraceSource ts;
  public MyLogger(string name)
  {
    ts = new TraceSource(name);
  }

  public void ILogger.Log(string msg)
  {
    ts.TraceEvent(msg);
  }
}

Et de l'utiliser comme ceci:

private static readonly ILogger logger = new MyLogger("stackoverflow");
logger.Info("Hello world!")

De passer à numéro 2 ... Comment faire pour résoudre un particulier nommé journal instance? Devrais-je tirer parti de l'application.les informations de configuration de la plateforme d'enregistrement de mon choix (c'est à dire résoudre les bûcherons basé sur le schéma de nommage dans l'application.config)? Ainsi, dans le cas de log4net, pourrais-je préfère à "injecter" LogManager (notez que je sais, c'est pas possible puisque c'est un objet statique)? J'ai pu envelopper LogManager (appeler MyLogManager), lui donner un ILogManager de l'interface, puis résoudre MyLogManager.ILogManager interface. Mes autres objets pourraient avoir un depenency (Import dans MEF jargon) sur ILogManager (Exportation de l'assemblée où il est mis en œuvre). Maintenant, je pourrais avoir des objets comme ceci:

public class MyClass
{
  private ILogger logger;
  public MyClass([Import(typeof(ILogManager))] logManager)
  {
    logger = logManager.GetLogger("MyClass");
  }
}

Tout moment ILogManager est appelée, elle serait directement délégué à log4net est LogManager. Sinon, l'enveloppé LogManager prendre la ILogger instances qu'il se base sur l'application.config et les ajouter à la(une ?) Conteneur MEF par son nom. Plus tard, quand un enregistreur du même nom est demandé, la enveloppé LogManager est interrogé pour ce nom. Si le ILogger est là, il est résolu de cette façon. Si c'est possible avec le MEF, est-il un bénéfice de le faire?

Dans ce cas, en réalité, que ILogManager est "injecté" et il peut main ILogger cas dans la façon dont log4net fait normalement. Comment fonctionne ce type d'injection (essentiellement d'une usine) comparer à injecter le nom de l'enregistreur de cas? Cela ne permettra plus facilement en tirant parti de log4net (ou autre plateforme d'enregistrement) application.fichier de configuration.

Je sais que je peux obtenir des instances nommées de la MEF conteneur comme ceci:

var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");

Mais comment puis-je obtenir les instances nommées dans le conteneur? Je sais que sur les attributs de base du modèle où je pourrais avoir des implémentations différentes de ILogger, chaque de ce qui est nommé (par l'intermédiaire d'un MEF attribut), mais qui n'a pas vraiment m'aider. Est-il un moyen de créer quelque chose comme une application.config (ou une section de celle-ci) que la liste des enregistreurs (tous de la même mise en œuvre) par nom et que la MEF pu lire? Pourrait/devrait-il y avoir une centrale de "manager" (comme MyLogManager) qui résout nommé enregistreurs via l'application sous-jacente.config puis insère le résolu logger dans le conteneur MEF? De cette manière, il serait disponible pour quelqu'un d'autre qui a accès à la même conteneur MEF (bien que sans le MyLogManager de connaissances sur la façon d'utiliser log4net app.les informations de configuration, il semble que le conteneur serait incapable de résoudre un nom de bûcherons directement).

Cela a déjà reçu assez long. J'espère que c'est cohérent. N'hésitez pas à partager aucune information spécifique sur la façon dont vous la dépendance injecté une plateforme d'enregistrement (nous sommes le plus probable compte tenu de log4net, NLog, ou quelque chose (j'espère mince), construit sur le Système.Diagnostics) de votre application.

Avez-vous injecter le "gestionnaire" et le retour de l'enregistreur de cas?

Avez-vous à ajouter vos propres informations de configuration dans votre propre section de configuration ou dans votre DI plate-forme de la section de configuration pour le rendre plus facile/possible d'injecter de l'enregistreur des instances directement (c'est à dire faire vos dépendances sur ILogger plutôt que ILogManager).

Ce que le fait d'avoir une statique ou conteneur global qui dispose de la ILogManager de l'interface ou de l'ensemble d'nommé ILogger instances en elle. Donc, plutôt que d'injecter dans le sens classique du terme (via le constructeur, de propriété, ou un membre de données), l'enregistrement de la dépendance est explicitement résolu à la demande. Est-ce une bonne ou une mauvaise façon de dépendance injecter.

Je suis ce marquage comme un wiki de la communauté, car il ne semble pas être une question avec une réponse définitive. Si quelqu'un se sent par ailleurs, n'hésitez pas à le changer.

Merci pour toute aide!