<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>xlab &#187; log4net</title>
	<atom:link href="http://xlab.pl/tag/log4net/feed/" rel="self" type="application/rss+xml" />
	<link>http://xlab.pl</link>
	<description>XSolve laboratory - dzielimy się tym co wiemy...</description>
	<lastBuildDate>Thu, 12 Apr 2012 07:23:58 +0000</lastBuildDate>
	<language>pl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Automatyczne nazywanie loggerów log4net, sposób drugi</title>
		<link>http://xlab.pl/automatyczne-nazywanie-logerow-log4net-sposob-drugi/</link>
		<comments>http://xlab.pl/automatyczne-nazywanie-logerow-log4net-sposob-drugi/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 20:33:33 +0000</pubDate>
		<dc:creator>Mateusz Kubiczek</dc:creator>
				<category><![CDATA[Programowanie .NET]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[extension methods]]></category>
		<category><![CDATA[log4net]]></category>

		<guid isPermaLink="false">http://www.xlab.pl/?p=324</guid>
		<description><![CDATA[Gwiazdorrr w komentarzu do poprzedniej notki o log4net przedstawił inny, niewątpliwie sprytny sposób automatyzacji pobierania nazwanego loggera za pomocą extension methods (metod rozszerzających): namespace Logging { public static class LogExtensions { public static ILog GetLog(this Object obj) { return LogManager.GetLogger(obj.GetType()); } } } public void TestLoggerName() { BasicConfigurator.Configure(); ILog log = GetLog(); Assert.That(log.Logger.Name, Is.EqualTo(”Test.LoggingTests”)); } [...]]]></description>
			<content:encoded><![CDATA[<p>Gwiazdorrr w komentarzu do <a href="http://www.xlab.pl/2009/08/automatyczne-nazywanie-logerow-log4net/">poprzedniej notki o log4net</a> przedstawił inny, niewątpliwie sprytny sposób automatyzacji pobierania nazwanego loggera za pomocą extension methods (metod rozszerzających):</p>
<pre name="code" class="c-sharp">
namespace Logging
{
    public static class LogExtensions
    {
        public static ILog GetLog(this Object obj)
        {
            return LogManager.GetLogger(obj.GetType());
        }
    }
}

public void TestLoggerName()
{
    BasicConfigurator.Configure();
    ILog log = GetLog();
    Assert.That(log.Logger.Name, Is.EqualTo(”Test.LoggingTests”));
}</pre>
<p>Jedyny problem z tym kodem to ta linijka, która się nie kompiluje:</p>
<pre name="code" class="c-sharp">
ILog log = GetLog();</pre>
<pre>
Error 1 The name 'Extension' does not exist in the current context
C:\VS2008\TestLogging\TestLogging\TestClass.cs</pre>
<p>Niemniej jednak, dodanie słowa kluczowego &#8222;this&#8221; wystarcza, żeby kod się skompilował.<br />
Ciekawe, prawda? Co ciekawsze, prawdopobnie przez to ubzdurałem sobie, że nie można wywoływać metod rozszerzających w kontekście klasy, którą rozszerzają. ;-) Oh well, tutaj poprawiony kod, dzięki gwiazdorrr! To tylko jeden z wielu świetnych sposobów na wykorzystanie tego elementu języka C#.<br />
Bardzo polecam <a href="http://stackoverflow.com/questions/271398/post-your-extension-goodies-for-c-net-codeplex-com-extensionoverflow">wątek na StackOverflow zawierający dziesiątki świetnych extension methods</a>. W przyszłości spróbuję skrobnąć więcej o metodach rozszerzających, których często używam.</p>
<pre name="code" class="c-sharp">
namespace Logging
{
    public static class LogExtensions
    {
        public static ILog GetLog(this Object obj)
        {
            return LogManager.GetLogger(obj.GetType());
        }
    }
}</pre>
<pre name="code" class="c-sharp">
public void TestLoggerName()
{
    BasicConfigurator.Configure();
    ILog log = this.GetLog();
    Assert.That(log.Logger.Name, Is.EqualTo(”Test.LoggingTests”));
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/automatyczne-nazywanie-logerow-log4net-sposob-drugi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatyczne nazywanie loggerów log4net</title>
		<link>http://xlab.pl/automatyczne-nazywanie-logerow-log4net/</link>
		<comments>http://xlab.pl/automatyczne-nazywanie-logerow-log4net/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 15:23:05 +0000</pubDate>
		<dc:creator>Mateusz Kubiczek</dc:creator>
				<category><![CDATA[Programowanie .NET]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[log4net]]></category>
		<category><![CDATA[pl]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.xlab.pl/?p=233</guid>
		<description><![CDATA[To polskie tłumaczenie poprzedniego artykułu (rozszerzone!). log4net jest frameworkiem służącym do logowania. Poznałem go dzięki setkom świetnych opinii w Internecie. Sposób użycia jest bardzo prosty, a zarazem niesamowicie elastyczny &#8211; po prostu logujemy wszystko za pomocą interfejsu ILog (dalej nazywam je po prostu &#8222;loggerami&#8221;, pewnie nie do końca po polsku :-)), a następnie konfigurujemy w [...]]]></description>
			<content:encoded><![CDATA[<h3><em>To polskie tłumaczenie poprzedniego <a href="http://www.xlab.pl/2009/04/auto-naming-log4net-loggers/">artykułu</a></em> (rozszerzone!).</h3>
<p><a href="http://logging.apache.org/log4net/index.html">log4net</a> jest frameworkiem służącym do logowania. Poznałem go dzięki setkom świetnych opinii w Internecie. Sposób użycia jest bardzo prosty, a zarazem niesamowicie elastyczny &#8211; po prostu logujemy wszystko za pomocą interfejsu <em> ILog</em> (dalej nazywam je po prostu &#8222;loggerami&#8221;, pewnie nie do końca po polsku :-)), a następnie konfigurujemy w XML-u (lub programistycznie), gdzie zarejestrowane logi mają trafiać.</p>
<p>Interfejs <em>ILog</em> możemy pobrać na użytek danej klasy na dwa sposoby:</p>
<ul>
<li>Wykorzystując typ (w tym przypadku naszej klasy, w której znajduje się logger, oczywiście może być to dowolny typ):</li>
</ul>
<pre name="code" class="c-sharp">
namespace Foo.Test
{
   public class MyTestClass
   {
      Ilog log = LogManager.GetLogger(typeof(MyTestClass));
   }
}</pre>
<ul>
<li>po prostu poprzez string:</li>
</ul>
<pre  name="code" class="c-sharp">namespace Foo.Test
{
   public class MyTestClass
   {
       Ilog log = LogManager.GetLogger("Mój obiekt logowania");
   }
}</pre>
<p>Jednak zalecam tę pierwszą metodę. Dlaczego? Bardzo ułatwia nam to <a href="http://logging.apache.org/log4net/release/manual/introduction.html#Logger%20hierarchy">hierarchiczną organizację logerów</a>. Dodatkowo, w pierwszym przypadku w naszych logach od razu pojawi się nazwa klasy wraz z przestrzenią nazw, czyli będziemy od razu widzieli &#8222;Foo.Test.MyTestClass&#8221;. Potencjalna refaktoryzacja (jak np. zmiana nazwy klasy, czy przestrzeni nazw) nie spowoduje, że będziemy musieli zmieniać nazwy naszych loggerów.</p>
<p>Niedawno, przeglądając kod projektu <a href="http://code.google.com/p/subtext/">Subtext</a> (tak, to robię po godzinach ;-)) wpadłem na fajny trick służący do pobierania loggerów. Co, gdybyśmy nie musieli jawnie podawać typu przy pobieraniu loggera, tylko pewna logika sama by znalazłaby typ klasy?</p>
<p>Może ten test rozjaśni, o co dokładnie chodzi:</p>
<pre  name="code" class="c-sharp">namespace Test
{
    using log4net;
    using log4net.Config;
    using NUnit.Framework;
    using NUnit.Framework.SyntaxHelpers;

    ﻿﻿[TestFixture]
    public class LoggingTests
    {
        [Test]
        public void TestLoggerName()
        {
            BasicConfigurator.Configure();
            ILog log = Logging.GetLog();

            Assert.That(log.Logger.Name, Is.EqualTo("Test.LoggingTests"));
        }
    }
}</pre>
<p>Chcielibyśmy dostać obiekt ILog bez konieczności podawania jawnie typu klasy. W tym przypadku chcemy uzyskać &#8222;Test.LoggingTests&#8221;, bo tak nazywa się klasa testu (klasa, która potrzebuje loggera).</p>
<p>Oczywiście ten test się nie skompiluje bez klasy Logging. Definiujemy ją z metodą GetLog, na razie zwracającą null:</p>
<pre name="code" class="c-sharp">public static class Logging
{
    public static ILog GetLog()
    {
        return null;
    }
}</pre>
<p>Udało nam się skompilować, oczywiście test zwraca błąd (tak jak powinien, jeżeli chcemy stosować najlepsze praktyki testów jednostkowych)!</p>
<p>Spróbujmy zaimplementować naszą klasę pomocniczą. Niech <em>GetLog</em> użyje metody <em>GetCallerType</em> do pobrania typu klasy, do której chcemy pobrać loggera. Zauważmy, że nigdzie nie podajemy co to za klasa.</p>
<pre name="code" class="c-sharp">public static ILog GetLog()
{
    return LogManager.GetLogger(GetCallerType());
}</pre>
<p>Zwróci to loggera o typie, który pobierze metoda:</p>
<pre name="code" class="c-sharp">[MethodImpl(MethodImplOptions.NoInlining)]
private static Type GetCallerType()
{
    return new StackFrame(2, false).GetMethod().DeclaringType;
}</pre>
<p>Ten malutki kawałek kodu pobiera ramkę ze stosu cofając się o dwie wywołania metod. Dla naszego testu, dostaniemy metodę <em>TestLoggerName</em>. Stąd już niedaleko, do pobrania typu klasy zawierającej tę metodę. Sprytne!</p>
<p>Test powinien przejść. Tutaj pełen kod naszej klasy pomocniczej:</p>
<pre name="code" class="c-sharp">using System;
using log4net;
using System.Runtime.CompilerServices;
using System.Diagnostics;

namespace Logging
{
    /// &lt;summary&gt;
    /// A static class to fetch the logger.
    /// &lt;/summary&gt;
    public static class Logging
    {
        /// &lt;summary&gt;
        /// This replaces the LogManager.GetLogger(typeof(CurrentClass)).
        /// You only need to declare the log in your class like this:
        /// protected ILog log = Logging.GetLog();
        /// &lt;/summary&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static ILog GetLog()
        {
            return LogManager.GetLogger(GetCallerType());
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static Type GetCallerType()
        {
            return new StackFrame(2, false).GetMethod().DeclaringType;
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/automatyczne-nazywanie-logerow-log4net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

