it-swarm.com.de

Injizieren von Log4Net ILog-Implementierungen mit Unity 2.0

Letztendlich hat dies mit der Einrichtung von log4Net zu tun, aber im Allgemeinen liegt das Problem nicht in der spezifischen Protokollierung.

Generell versuche ich herauszufinden, wie in Microsoft Unity 2.0 etwas getan wird, das dem entspricht, was man mit Castle.Facilities.Logging.LoggingFacility erhält. Die Fähigkeit, eine Abhängigkeit von einem Protokollierer zu deklarieren und den Protokollierer mit dem Typ des Objekts initialisieren zu lassen, in das er injiziert wird.

Im Geiste eines Tests sagt mehr als tausend Worte, hier ist was ich brauche:

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

Ich weiß nicht, ob Sie danach suchen, aber ich habe es vor einigen Monaten gesehen und wurde daran erinnert, als ich Ihre Frage sah. Ich habe Unity nicht verwendet, daher kann ich nicht wirklich vergleichen, was Sie mit dem, was sich unter dem Link befindet, gepostet haben. Hoffentlich wird es Ihnen nützlich sein:

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

13
wageoghe

Ich habe versucht, das gleiche Ergebnis zu erzielen, indem ich in der Lage war, korrekt konfigurierte ILog -Instanzen mithilfe der Konstruktorinjektion mit Unity in eine Abhängigkeit einzufügen.

Am Ende habe ich meine eigene "log4net" -Einheitserweiterung geschrieben, um genau dies zu tun (teilweise inspiriert durch einen Blog-Beitrag, den ein anderer Antwortender, Kenneth Baltrinic, geschrieben hat).

So können Sie die Erweiterung einmalig bei Unity registrieren:

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

und dann die richtige ILog-Logger-Instanz übergeben:

public class MyClass
{
    private readonly ILog logger;

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

Die Erweiterung finden Sie hier:

https://github.com/roblevine/UnityLoggingExtensions

Weitere Informationen finden Sie hier: http://blog.roblevine.co.uk/net/using-log4net-with-unity/

EDITdies ist jetzt als NuGet-Paket verfügbar

9
Rob Levine

Nachdem ich mich stundenlang im Unity-Quellcode umgesehen hatte, kam ich auf die folgende Lösung. Ich würde es jedoch vorziehen, einen Weg zu finden, um den geeigneten Abhängigkeitsauflöser basierend auf dem aufzulösenden Typ festzulegen, anstatt die standardmäßige Konstruktorauswahlrichtlinie zu überschreiben. Zum einen, weil ich zuvor den Standardkonstruktor-Selektor für andere Zwecke überschrieben habe. Zum anderen verarbeitet diese Lösung nur Abhängigkeiten, die über den Konstruktor eingefügt werden. Für eine vollständige Abdeckung müsste man vermutlich auch die Standardeigenschafts- und Methodenselektoren überschreiben. Für mich brauche ich nur Konstrukteure.

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

Die obige Erweiterung funktioniert gut, für MVC5-Benutzer sind jedoch weitere Konfigurationsinformationen erforderlich. Hier sind die Schritte unter Verwendung der Einheit.

Fügen Sie die folgende Zeile am oberen Rand Ihrer startup.cs-Klasse über dem Namespace hinzu.

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

Fügen Sie in Ihrer global.asax application_startup -Methode die folgenden Informationen hinzu:

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

Der Rest der Konfiguration für den Einheitscontainer sollte wie folgt aussehen:

container.AddNewExtension<Log4NetExtension>();

Stellen Sie sicher, dass Ihrer web.config eine appender hinzugefügt wurde. Das sollte es sein, damit das richtig funktioniert. Viel Glück

2
fighter68

Ab Unity 5 können Sie jetzt die Log4Net-Erweiterung von Unity unter https://github.com/unitycontainer/log4net verwenden.

Alles was Sie tun müssen, ist das Nuget zu installieren und die Erweiterung zu Ihrem Container hinzuzufügen:

container.AddNewExtension<Log4NetExtension>();

Und es funktioniert automatisch mit allen Klassen, die ILog als Abhängigkeit verwenden.

1
yvesmancera

Sie können den folgenden Code verwenden, um Log4Net zu injizieren

log4net.Config.BasicConfigurator.Configure();    

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

typeof (Programm) wird verwendet, da ich mich in der Programmklasse registriere. Use kann den Klassennamen oder dieses Schlüsselwort verwenden

Dann können Sie ILog in die Klasse injizieren

 public class MyClass
 {
   private readonly ILog logger;

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