web-dev-qa-db-fra.com

Commentaire injecteur des implémentations Log4Net ILog sous Unity 2.0

En fin de compte, cela concerne la configuration de log4Net, mais le problème n’est pas lié à la journalisation.

Généralement, ce que je cherche à savoir, c'est comment faire, dans Microsoft Unity 2.0, quelque chose d’équivalent à ce que l’on obtient avec Castle.Facilities.Logging.LoggingFacility. À savoir la possibilité de déclarer une dépendance sur un enregistreur et d’initialiser l’enregistreur avec le type de l’objet dans lequel il est injecté.

Dans l’esprit d’un test qui vaut mille mots, voici ce dont j’ai besoin:

class Logger_IOC_Tests
{
    //[Test] 
    public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
    {
        var container = new UnityContainer();
        /* Configuration Magic probably involiving registering either 
            * a custom IDependencyResolverPolicy or BuilderStrategy
            * goes here...
            */
        container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());

        var user = container.Resolve<LoggerUser>();

        Assert.True(user.Logger.GetUserType() == user.GetType());
    }
}

interface ILogger
{
    Type GetUserType();
}

class Logger : ILogger
{
    private readonly Type _type;

    public Logger(Type type)
    {
        _type = type;
    }

    public Type GetUserType()
    {
        return _type;
    }
}

class LoggerUser
{
    public readonly ILogger Logger;

    public LoggerUser(ILogger logger)
    {
        Logger = logger;
    }
}
18
Kenneth Baltrinic

Je ne sais pas si c'est ce que vous recherchez, mais je l'ai vu il y a quelques mois et je l'ai rappelé lorsque j'ai vu votre question. Je n'ai pas utilisé Unity, donc je ne peux pas vraiment comparer ce que vous avez posté avec ce qui est sur le lien. J'espère que cela vous sera utile:

http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html

13
wageoghe

J'ai essayé d'obtenir le même résultat, à savoir pouvoir insérer des instances ILog correctement configurées dans une dépendance à l'aide de l'injection de constructeur avec Unity.

À la fin, j’ai écrit ma propre extension d’unité "log4net" dans ce but (inspiré en partie par un billet de blog écrit par un autre répondeur, Kenneth Baltrinic).

Cela vous permet d’enregistrer l’extension une fois avec Unity:

var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();

et faites ensuite passer l'instance de journalisation ILog appropriée:

public class MyClass
{
    private readonly ILog logger;

    public MyClass(ILog logger)
    {
        this.logger = logger;
    }
}

L'extension peut être trouvée ici:

https://github.com/roblevine/UnityLoggingExtensions

Plus d'infos ici: http://blog.roblevine.co.uk/net/using-log4net-with-unity/

EDITceci est maintenant disponible sous forme de paquet NuGet

9
Rob Levine

Après des heures passées à explorer le code source de Unity, j'ai proposé la solution suivante. Cependant, je préférerais trouver un moyen de définir le résolveur de dépendance approprié en fonction du type en cours de résolution plutôt que de remplacer la stratégie de sélecteur de constructeur par défaut. D'une part, parce que j'avais précédemment substitué le sélecteur de constructeur par défaut à d'autres fins. D'autre part, cette solution ne gère que les dépendances injectées via le constructeur. Pour une couverture complète, il faudrait remplacer les sélecteurs de propriétés et de méthodes par défaut. Pour moi, je n'ai besoin que de constructeurs.

class Logger_IOC_Tests
{
    [Test] 
    public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
    {
        var container = new UnityContainer();
        container.AddNewExtension<LoggingExtension>();
        container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
        var user = container.Resolve<LoggerUser>();

        Assert.True(user.Logger.GetUserType() == user.GetType());
    }
}

class LoggingExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy()); 
    }
}

public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
    protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
    {
        return parameter.ParameterType == typeof(ILogger) 
                   ? new LoggerResolverPolicy(parameter.Member.DeclaringType) 
                   : base.CreateResolver(parameter);
    }
}

class LoggerResolverPolicy : IDependencyResolverPolicy
{
    private readonly Type _dependantType;

    public LoggerResolverPolicy(Type dependantType)
    {
        _dependantType = dependantType;
    }

    public object Resolve(IBuilderContext context)
    {
        return new Logger(_dependantType);
    }
}
4
Kenneth Baltrinic

L'extension ci-dessus fonctionne bien, mais davantage d'informations de configuration sont nécessaires pour les utilisateurs de MVC5. Voici les étapes en utilisant l'unité.

Ajoutez la ligne suivante en haut de votre classe startup.cs au-dessus de l'espace de noms.

[Assembly: log4net.Config.XmlConfigurator (ConfigFile = "Web.config", Watch = true)]

Dans votre méthode global.asax application_startup, ajoutez les informations suivantes:

log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));

Le reste de la configuration du conteneur d'unité doit être tel quel:

container.AddNewExtension<Log4NetExtension>();

Assurez-vous d’avoir ajouté une appender à votre web.config. Cela devrait être pour que cela fonctionne correctement. Bonne chance

2
fighter68

Avec Unity 5 et les versions ultérieures, vous pouvez désormais utiliser la propre extension Log4Net de Unity à partir de https://github.com/unitycontainer/log4net .

Tout ce que vous avez à faire est d'installer le Nuget et d'ajouter l'extension à votre conteneur:

container.AddNewExtension<Log4NetExtension>();

Et cela fonctionnera automatiquement avec toutes les classes qui utilisent ILog comme dépendance.

1
yvesmancera

Vous pouvez utiliser le code suivant pour injecter Log4Net

log4net.Config.BasicConfigurator.Configure();    

container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));

typeof (programme) est utilisé depuis mon inscription en classe de programme. Utilisez peut utiliser le nom de la classe ou ce mot clé

Ensuite, vous pouvez injecter ILog dans la classe

 public class MyClass
 {
   private readonly ILog logger;

   public MyClass(ILog logger)
   {
     this.logger = logger;
   }
 }
0
Sathish