<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Elemar DEV</title>
	<atom:link href="http://elemarjr.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://elemarjr.net</link>
	<description>Tecnologia e desenvolvimento .net</description>
	<lastBuildDate>Tue, 22 May 2012 02:15:09 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='elemarjr.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/5ea29b775e2b805f0f1e9fbebf132906?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Elemar DEV</title>
		<link>http://elemarjr.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://elemarjr.net/osd.xml" title="Elemar DEV" />
	<atom:link rel='hub' href='http://elemarjr.net/?pushpress=hub'/>
		<item>
		<title>Usando Asp.net Web API HttpClient para consumir servi&#231;os REST</title>
		<link>http://elemarjr.net/2012/05/21/usando-asp-net-web-api-httpclient-para-consumir-servios-rest/</link>
		<comments>http://elemarjr.net/2012/05/21/usando-asp-net-web-api-httpclient-para-consumir-servios-rest/#comments</comments>
		<pubDate>Tue, 22 May 2012 02:12:14 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[AspNetMvc]]></category>
		<category><![CDATA[async]]></category>
		<category><![CDATA[Learning Tests]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[WebAPI]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2830</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Asp.net Web API é uma excelente&#160; alternativa para desenvolvimento de serviços Web. Pessoalmente, acredito que ela vai revolucionar a forma como desenvolvemos aplicativos. Um dos pontos fortes dessa biblioteca é a facilidade de consumir serviços produzidos com ela em JavaScript&#160; &#8211; visto que eles operam facilmente através de HTTP/Json. Entretanto, para [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2830&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p><a href="http://www.asp.net/web-api">Asp.net Web API</a> é uma excelente&#160; alternativa para desenvolvimento de serviços Web. Pessoalmente, acredito que ela vai revolucionar a forma como desenvolvemos aplicativos.</p>
<p>Um dos pontos fortes dessa biblioteca é a facilidade de consumir serviços produzidos com ela em JavaScript&#160; &#8211; visto que eles operam facilmente através de HTTP/Json. Entretanto, para aplicativos desenvolvidos em outras linguagens “a coisa” não é tão simples. HttpClient, que é parte do Asp.net Web API, facilita consideravelmente o desenvolvimento de clientes desse tipo.</p>
<p>Para ilustrar como HttpClient funciona, desenvolvi algum código demonstrativo e alguns learning tests. Eles <a href="https://github.com/ElemarJR/Learning.HttpClient">estão no Github</a>. Nesse post, mostro trechos de código mais importantes.</p>
<h2>O serviço que desejamos consumir</h2>
<p>O serviço que desejamos consumir é um “CRUD” para essa entidade:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4f2517c2-a711-4557-91ca-4966d43b03b2" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
namespace Learning.HttpClientAPI.Entities
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }
}
</pre>
</pre>
</div>
<p>Que é mantido por esse repositório:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:c41e4500-78d8-4906-95bb-7d7e4350f16b" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System.Linq;
using System.Collections.Generic;

using Learning.HttpClientAPI.Entities;


namespace Learning.HttpClientAPI.Repositories
{
    public class PeopleRepository
    {   
        List&lt;Person&gt; data = new List&lt;Person&gt;
        {
            new Person {Id=1, Name=&quot;John Doe&quot;, Email=&quot;john@hotmail.com&quot;},
            new Person {Id=2, Name=&quot;Mike Myers&quot;, Email=&quot;myers@hotmail.com&quot;},
            new Person {Id=3, Name=&quot;Joseph Climber&quot;, Email = &quot;climber@hotmail.com&quot;},
            new Person {Id=1, Name=&quot;Mikaela Romanova&quot;, Email=&quot;mika@hotmail.com&quot;},
        };

        private int newId = 4;

        public IEnumerable&lt;Person&gt; GetAll()
        {
            return data;
        }

        public Person Get(int id)
        {
            return data.FirstOrDefault(person =&gt; person.Id == id);
        }

        public Person Add(Person person)
        {
            person.Id = newId++;
            data.Add(person);
            return person;
        }

        public bool Update(Person person)
        {
            var index = data.FindIndex(p =&gt; p.Id == person.Id);
            if (index == -1) return false;

            data[index] = person;
            return true;
        }

        public void Remove(int id)
        {
            var index = data.FindIndex(p =&gt; p.Id == id);
            if (index == -1) return;
            data.RemoveAt(index);
        }
    }
}
</pre>
</pre>
</div>
<p>Como pode ver, esse repositório mantém dados apenas em memória. </p>
<p>Agora, o serviço:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:0eeefa78-d7a8-41c9-9498-d2836e77b22c" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Net;

using System.Net.Http;
using System.Web.Http;

using Learning.HttpClientAPI.Entities;
using Learning.HttpClientAPI.Repositories;

namespace Learning.HttpClientAPI.Controllers
{
    public class PeopleController : ApiController
    {
        static readonly PeopleRepository repository = 
            new PeopleRepository();

        public IEnumerable&lt;Person&gt; Get()
        {
            return repository.GetAll();
        }

        public Person Get(int id)
        {
            var result = repository.Get(id);
            if (result == null)
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            return result;
        }

        public HttpResponseMessage Post(Person newPerson)
        {
            newPerson = repository.Add(newPerson);

            var result = Request.CreateResponse(HttpStatusCode.Created);
            result.Content = result.CreateContent(newPerson);
            var url = Url.Route(&quot;DefaultApi&quot;, new { id = newPerson.Id });
            result.Headers.Location = new Uri(url, UriKind.Relative);
            
            return result;
        }

        public void Put(int id, Person person)
        {
            person.Id = id;
            if (!repository.Update(person))
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }

        public HttpResponseMessage Delete(int id)
        {
            repository.Remove(id);
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
}
</pre>
</pre>
</div>
<p>Tomei o cuidado de seguir as recomendações de implementação do Http.</p>
<h2>Um exemplo simples usando HttpClient</h2>
<p>Agora, vamos ver como consumir esse serviço usando HttpClient. Para mostrar como HttpClient funciona, comecemos com um projeto console simples.</p>
<p>Para começar, referências:</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image39.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb39.png?w=554&h=371" width="554" height="371" /></a></p>
<p>Essas são as referências necessárias para HttpClient. Como já é prática, utilizei NuGet para adicionar as referências que são necessárias.</p>
<p>Agora, vejamos a implementação:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:757d4a17-0e38-4567-a5d8-c388c0525e4e" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System.Json;
using System.Net.Http;

namespace Learning.HttpClient.Console
{
    internal class Program
    {
        private static void Main()
        {
            var client = new System.Net.Http.HttpClient();
 
            client.GetAsync(&quot;http://localhost:8585/api/people&quot;)
                .ContinueWith(requestTask =&gt;
                {
                    var response = requestTask.Result;
                    response.EnsureSuccessStatusCode();

                    response.Content.ReadAsAsync&lt;JsonArray&gt;().ContinueWith(readTask =&gt;
                    {
                        foreach (var item in readTask.Result)
                        {
                            System.Console.WriteLine(item[&quot;Name&quot;]);
                        }
                    });
                });
 
            System.Console.ReadLine();
        }
    }
}
</pre>
</pre>
</div>
<p>Repare que:</p>
<ul>
<li>“Tudo acontece” em torno do objeto HttpClient;</li>
<li>Toda implementação foi planejada para suporte assíncrono;</li>
</ul>
<p>Penso que o código é auto-explicativo, então …</p>
<p>Agora, vejamos a facilidade que o <strong><em>async</em></strong> do C# 5 vai trazer (veja os <a href="http://elemarjr.net/tag/async/">posts que já escrevi sobre o tema</a>):</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:3bb9aa56-5487-465a-897f-dc890c2baa47" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System.Json;
using System.Net.Http;

namespace Learning.HttpClient.ConsoleWithAsync
{
    internal class Program
    {
        private static void Main()
        {
            GetData();
            
            System.Console.ReadLine();
        }

        private static async void GetData()
        {
            var client = new System.Net.Http.HttpClient();

            var response = await client.GetAsync(&quot;http://localhost:8585/api/people&quot;);
            response.EnsureSuccessStatusCode();
            var people = await response.Content.ReadAsAsync&lt;JsonArray&gt;();

            foreach (var person in people)
            {
                System.Console.WriteLine(person[&quot;Name&quot;]);
            }
        }
    }
}
</pre>
</pre>
</div>
<p>Bem mais limpo. Não acha?!</p>
<h2>Learning Tests</h2>
<p>Para entender como HttpClient funciona, de verdade, vamos escrever também alguns <a href="http://elemarjr.net/tag/learning-tests/">learning tests</a>.</p>
<h3>Referências</h3>
<p>Como estamos em um projeto de testes, com automação, adicionei IISExpress Automation Library (que <a href="http://elemarjr.net/2012/05/19/iisexpress-automation-agora-est-disponvel-no-nuget/">desenvolvemos há aqui no blog</a>).</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image40.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb40.png?w=554&h=371" width="554" height="371" /></a></p>
<h3>Implementação</h3>
<p>Nossos exemplos, até aqui, foram simples. Agora, vamos ver como executar todas as operações associadas com um CRUD. </p>
<p>Eis os testes:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:414a462d-7889-4789-a069-144937fa61c1" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.IO;
using System.Net.Http.Formatting;
using NUnit.Framework;
using SharpTestsEx;
using IISExpressAutomation;

using System.Threading;
using System.Net.Http;
using System.Json;
using System.Net.Http.Headers;

using Learning.HttpClientAPI.Entities;
using System.Net;

namespace Learning.HttpClientAPI.Tests
{
    [TestFixture]
    public class GettingStarted
    {
        private IISExpress iis;

        [TestFixtureSetUp]
        public void Setup()
        {
            var path = Path.GetFullPath(@&quot;..\..\..\Learning.HttpClient&quot;);
            Console.WriteLine(path);
            iis = new IISExpress(new Parameters
                    {
                        Port = 8585,
                        Path = path
                    }
                );
            Thread.Sleep(1000);
        }

      
        [Test]
        public void GettingAllData()
        {
            var client = new HttpClient();

            var getAsyncResult = client.GetAsync(&quot;http://localhost:8585/api/people&quot;).Result;
            getAsyncResult.EnsureSuccessStatusCode();
            var data = getAsyncResult.Content.ReadAsAsync&lt;JsonArray&gt;().Result;
            data.Count.Should().Be.GreaterThanOrEqualTo(3);

            foreach (var item in data)
                Console.WriteLine(item[&quot;Name&quot;]);

            client.Dispose();
        }

        [Test]
        [TestCase(1, &quot;John Doe&quot;)]
        [TestCase(2, &quot;Mike Myers&quot;)]
        [TestCase(3, &quot;Joseph Climber&quot;)]
        public void GettingItem(int id, string expectedName)
        {
            var client = new HttpClient();

            var address = string.Format(&quot;http://localhost:8585/api/people/{0}&quot;, id);

            var getAsyncResult = client.GetAsync(address).Result;
            getAsyncResult.EnsureSuccessStatusCode();
            var person = getAsyncResult.Content.ReadAsAsync&lt;Person&gt;().Result;
            person.Name.Should().Be(expectedName);
                    
            client.Dispose();
        }

        [Test]
        public void ResourceNotFound()
        {
            using (var client = new HttpClient())
            {
                const string address = &quot;http://localhost:8585/api/people/10&quot;;
                var getAsyncResult = client.GetAsync(address).Result;
                getAsyncResult.Executing(g =&gt; g.EnsureSuccessStatusCode())
                    .Throws&lt;HttpRequestException&gt;();
            }
        }

        [Test]
        public void PostItem()
        {
            var newPerson = new Person
            {
                Name = &quot;Mary Jo&quot;,
                Email = &quot;maryjo@hotmail.com&quot;
            };

            using (var client = new HttpClient())
            {
                const string address = &quot;http://localhost:8585/api/people&quot;;
                var requestMessage =  CreateHttpRequestMessage(newPerson);

                var postAsyncResult = client.PostAsync(address, requestMessage.Content).Result;
                postAsyncResult.EnsureSuccessStatusCode();

                var person = postAsyncResult.Content.ReadAsAsync&lt;Person&gt;().Result;
                person.Name.Should().Be(newPerson.Name);
                person.Id.Should().Be.GreaterThanOrEqualTo(4);
            }
        }

        [Test]
        public void PuItem()
        {
            string expectedName;
            var updatedPerson = new Person
            {
                Id = 2,
                Name = expectedName = &quot;Malcon Myers&quot;,
                Email = &quot;mmyers@hotmail.com&quot;
            };

            using (var client = new HttpClient())
            {
                const string address = &quot;http://localhost:8585/api/people/2&quot;;
                var requestMessage = CreateHttpRequestMessage(updatedPerson);

                var putAsyncResult = client.PutAsync(address, requestMessage.Content).Result;
                putAsyncResult.EnsureSuccessStatusCode();

                var getAsyncResult = client.GetAsync(address).Result;
                getAsyncResult.EnsureSuccessStatusCode();
                var person = getAsyncResult.Content.ReadAsAsync&lt;Person&gt;().Result;
                person.Name.Should().Be(expectedName);
            }
        }

        private HttpRequestMessage CreateHttpRequestMessage&lt;T&gt;(T data)
        {
            var mediaType = new MediaTypeHeaderValue(&quot;application/json&quot;);

            var jsonFormatter = new JsonMediaTypeFormatter();
            var requestMessage = new HttpRequestMessage&lt;T&gt;(data, mediaType, new MediaTypeFormatter[] {jsonFormatter});

            return requestMessage;
        }

        [Test]
        public void DeleteItem()
        {
            using (var client = new HttpClient())
            {
                const string address = &quot;http://localhost:8585/api/people/4&quot;;
                var deleteAsyncResult = client.DeleteAsync(address).Result;
                deleteAsyncResult.EnsureSuccessStatusCode();
                deleteAsyncResult.StatusCode.Should().Be(HttpStatusCode.NoContent);
            }
            
        }

        [TestFixtureTearDown]
        public void TearDown()
        {
            iis.Dispose();
        }

    }
}
</pre>
</pre>
</div>
<p>O que eu gostaria de destacar:</p>
<ul>
<li>Forcei uma implementação assíncrona requisitando a propriedade Result de cada método assíncrono de HttpClient;</li>
<li>O método <strong><em>EnsureSucessStatusCode</em></strong> garante que o serviço retornou adequadamente;</li>
<li>Há um método para cada verbo Http que necessitamos para “conversar” com nosso serviço.</li>
</ul>
<p>Vejamos os testes em execução:</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image41.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb41.png?w=554&h=341" width="554" height="341" /></a></p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/aspnetmvc/'>AspNetMvc</a>, <a href='http://elemarjr.net/tag/async/'>async</a>, <a href='http://elemarjr.net/tag/learning-tests/'>Learning Tests</a>, <a href='http://elemarjr.net/tag/rest/'>REST</a>, <a href='http://elemarjr.net/tag/webapi/'>WebAPI</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2830/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2830/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2830/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2830&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/21/usando-asp-net-web-api-httpclient-para-consumir-servios-rest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb39.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb40.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb41.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Mens sana in corpore sano</title>
		<link>http://elemarjr.net/2012/05/20/mens-sana-in-corpore-sano/</link>
		<comments>http://elemarjr.net/2012/05/20/mens-sana-in-corpore-sano/#comments</comments>
		<pubDate>Sun, 20 May 2012 23:40:42 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[DevEmForma]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2817</guid>
		<description><![CDATA[Olá pessoal. Tudo certo!? Quem disse que uma má notícia precisa ser ruim no todo?! Meses atrás, descobri que sou diabético. Depois de anos de descuido comigo mesmo, dieta extremamente irresponsável e, acima de tudo, uma vida para lá de sedentária, vi minha rotina diária ser “forçosamente” modificada. O que eu mudei?! De um dia [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2817&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo!?</p>
<p>Quem disse que uma má notícia precisa ser ruim no todo?!</p>
<p>Meses atrás, descobri que sou diabético. Depois de anos de descuido comigo mesmo, dieta extremamente irresponsável e, acima de tudo, uma vida para lá de sedentária, vi minha rotina diária ser “forçosamente” modificada.</p>
<h2>O que eu mudei?!</h2>
<p>De um dia para o outro, eu, que não cuidava o que comia, passei a uma dieta saudável (com direito a saladas e tudo mais). Mais importante que isso: eu, que nunca havia pisado em uma academia de ginástica, passei a ser frequentador assíduo. Há semanas em que apareço seis vezes por lá. Se não bastasse, eu, que não gostava de sair, passei a buscar meios bacanas de me divertir. Comecei a dançar (algo que eu sempre gostei) e, o que é mais incrível, comecei a sair para dançar.</p>
<h2>Tudo é uma questão de hábito</h2>
<p>Não vou mentir. Já odiei saladas. Tinha pavor sincero de comida saudável. Havia semanas em que comia “junk-food” todos os dias. Já foi rotina, por exemplo, tomar mais de 2 litros de coca-cola em um turno. Hoje, sou disciplinado. Entendi que é “comer para viver” e não o contrário.</p>
<p>Não conseguia me imaginar saindo de casa para ir a uma academia! Pensava: “esteira?! bicicleta?! Nem pensar! Andar tanto e não sair do lugar – coisa de louco.”. Lembro que, no meu primeiro dia na academia, mal aguentei caminhar 20 min. Hoje, vou a academia regularmente e venho aumentando minhas cargas consideravelmente. Se não posso dizer que gosto, já posso dizer que, quando não vou, sinto falta.</p>
<p>Também não gostava de sair de casa. Adorava minha cama, meu sofá. Ano passado, resolvi mudar isso também, Fui fazer aulas de dança. Aprendi (de verdade) a sambar e… descobri que adoro isso! Hoje, saio quase toda semana.</p>
<p>Há quem diga que bastam 21 repetições para criar um novo hábito. Não sei se é verdade, mas, para mim, bastou apenas boa vontade.</p>
<p>Se o homem se acostuma a tudo, inclusive a viver mal, por que não se acostumar com o bom?!</p>
<h2>Com o tempo, desafios são superados</h2>
<p>Eu, que não caminhava até a esquina, resolvi ir um pouco mais longe. Hoje, por exemplo, acordei as 4 da manhã (sim, em um domingo), peguei o carro, fui até Porto Alegre, e corri o “<a href="http://circuitodasestacoes.com.br/">Circuito das Estações</a>”. Foram 5km correndo, sem pausa para caminhadas e.. foi muito bom.</p>
<p align="center">
<p>Ainda não estou em forma e, por isso, me senti, inicialmente, um pouco deslocado. Todo mundo parecia tão bem! Mas, tinha um objetivo. Um desafio, na verdade. Queria correr 5 km, sem pausas para caminhar, na rua. Consegui!</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image37.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb37.png?w=281&h=373" width="281" height="373" /></a></p>
<p>Sei que não é bonito, mas, me sentia bem, mesmo “gordinho” (ainda!), passando os “em forma” que cansavam e começavam a caminhar. </p>
<h2>Novo contexto, boas amizades</h2>
<p>Obviamente, tudo fica muito melhor quando temos boas amizades. Hoje, por exemplo, contei com a companhia e apoio do meu amigo <a href="http://www.facebook.com/profile.php?id=100002442615369">Anderson Comberlato</a> (colega de trabalho e ex-aluno de informática [há quase 15 anos atrás]) e a <a href="http://www.facebook.com/katiapweber">Kátia Webber</a> (minha personal trainer e grande amiga).</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image38.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb38.png?w=410&h=258" width="410" height="258" /></a></p>
<p>Conhecer gente nova, com bons hábitos, é algo muito bom.</p>
<h2>Alguns resultados</h2>
<p>Compilando alguns resultados, posso dizer:</p>
<ul>
<li>Quando comecei, pesava 140Kg. Hoje, peso 106Kg (ainda estou obeso, mas faltam só 3Kg para deixar essa categoria).</li>
<li>Quando comecei, não conseguia caminhar 20 minutos. Hoje, CORRO 5Km, NA RUA.</li>
<li>Quando comecei, comia “junk-food” e dormia mal. Hoje, tenho uma dieta saudável e digo: “Sim, MVPs dormem!”</li>
</ul>
<h2>Concluindo…</h2>
<p><strong>Mens sana in corpore sano</strong> faz sentido! Se não estou “pensando bem”, posso dizer que, com certeza, estou “pensando melhor”.</p>
<p>BTW, há mais fotos do dia de hoje no <a href="http://facebook.com/elemarjr">meu Facebook</a>.</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/devemforma/'>DevEmForma</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2817/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2817/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2817/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2817&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/20/mens-sana-in-corpore-sano/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb37.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb38.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>IISExpress Automation agora est&#225; dispon&#237;vel no NuGet</title>
		<link>http://elemarjr.net/2012/05/19/iisexpress-automation-agora-est-disponvel-no-nuget/</link>
		<comments>http://elemarjr.net/2012/05/19/iisexpress-automation-agora-est-disponvel-no-nuget/#comments</comments>
		<pubDate>Sun, 20 May 2012 01:46:57 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[Aviso]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[NuGet]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2811</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! No último post, mostrei como controlar o IISExpress através de código em C#. Depois de publicado o post, resolvi trabalhar um pouco mais naquele código e&#160; disponibilizar o resultado no NuGet. Para obter o pacote Resolvi chamar esse pequena contribuição de “IISExpress Automation Library”. Ela já está disponível no NuGet. Sobre [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2811&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>No <a href="http://elemarjr.net/2012/05/18/promovendo-automao-para-o-iisexpress/">último post</a>, mostrei como controlar o IISExpress através de código em C#. </p>
<p>Depois de publicado o post, resolvi trabalhar um pouco mais naquele código e&#160; disponibilizar o resultado no <a href="https://nuget.org/packages/IISExpress.Automation/0.1.1">NuGet</a>.</p>
<h2>Para obter o pacote</h2>
<p>Resolvi chamar esse pequena contribuição de “IISExpress Automation Library”. Ela já está disponível no NuGet.</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image35.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb35.png?w=554&h=371" width="554" height="371" /></a></p>
<h2>Sobre o código-fonte</h2>
<p>O código-fonte foi revisado e melhorado. Está integralmente <a href="https://github.com/ElemarJR/IISExpress.Automation">disponível no GitHub</a>.</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image36.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb36.png?w=554&h=391" width="554" height="391" /></a></p>
<p>Espero contribuições.</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/aviso/'>Aviso</a>, <a href='http://elemarjr.net/tag/foss/'>FOSS</a>, <a href='http://elemarjr.net/tag/iis/'>IIS</a>, <a href='http://elemarjr.net/tag/nuget/'>NuGet</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2811/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2811&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/19/iisexpress-automation-agora-est-disponvel-no-nuget/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb35.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb36.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Controlando o IISExpress, no c&#243;digo, atrav&#233;s de automa&#231;&#227;o</title>
		<link>http://elemarjr.net/2012/05/18/promovendo-automao-para-o-iisexpress/</link>
		<comments>http://elemarjr.net/2012/05/18/promovendo-automao-para-o-iisexpress/#comments</comments>
		<pubDate>Fri, 18 May 2012 23:57:55 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[UIAutomation]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2801</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Você conhece o IISExpress? Em caso negativo, recomendo que leia esse post do Scott Guthrie. IISExpress é uma excelente alternativa para que possamos levantar nossos sites e/ou serviços para realizar testes de aceitação. Como ele está baseado em um utilitário de linha de comando, mostro aqui um exemplo simples de automação [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2801&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Você conhece o IISExpress? Em caso negativo, recomendo que leia esse <a href="http://weblogs.asp.net/scottgu/archive/2010/06/28/introducing-iis-express.aspx">post do Scott Guthrie</a>.</p>
<p>IISExpress é uma excelente alternativa para que possamos levantar nossos sites e/ou serviços para realizar testes de aceitação. </p>
<p>Como ele está baseado em um utilitário de linha de comando, mostro aqui um exemplo simples de automação para que possamos controlar o mesmo em nossos códigos.</p>
<p>Esse post será, fundamentalmente, código. Se você deseja entender melhor como funciona automação de interfaces, recomendo ler os <a href="http://elemarjr.net/tag/uiautomation/">outros posts que já escrevi sobre o tema</a>.</p>
<h2>Automação para IISExpress</h2>
<p>No código que segue, assumo que o IISExpress está instalado na sua pasta padrão. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:738f9496-89e2-4c8a-a2e6-9d3a92ec85e8" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Automation
{
    internal class NativeMethods
    {
        // Methods
        [DllImport(&quot;user32.dll&quot;, SetLastError = true)]
        internal static extern IntPtr GetTopWindow(IntPtr hWnd);

        [DllImport(&quot;user32.dll&quot;, SetLastError = true)]
        internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

        [DllImport(&quot;user32.dll&quot;, SetLastError = true)]
        internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);

        [DllImport(&quot;user32.dll&quot;, SetLastError = true)]
        internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    }

    internal class IISExpressProcessEnvelope : IDisposable
    {
        private readonly Process process;

        public IISExpressProcessEnvelope(Process process)
        {
            this.process = process;
        }

        #region IDisposable Members

        public void Dispose()
        {
            NativeMethods.PostMessage(
                GetHandleRef(), 
                0x12, 
                IntPtr.Zero, 
                IntPtr.Zero
                );
            process.Dispose();
        }

        #endregion

        private HandleRef GetHandleRef()
        {
            IntPtr ptr = NativeMethods.GetTopWindow(IntPtr.Zero);

            while (ptr != IntPtr.Zero)
            {
                uint num;
                NativeMethods.GetWindowThreadProcessId(ptr, out num);
                if (process.Id == num)
                    return new HandleRef(null, ptr);
                ptr = NativeMethods.GetWindow(ptr, 2);
            }

            throw new NullReferenceException(&quot;Process window not found.&quot;);
        }
    }

    public class IISExpress : IDisposable
    {
        private readonly IISExpressProcessEnvelope process;

        public IISExpress(int port, string path)
        {
            var info = new ProcessStartInfo
            {
                FileName = @&quot;c:\Program Files (x86)\IIS Express\iisexpress.exe&quot;,
                Arguments = string.Format(&quot;/port:{0} /path:{1}&quot;, port, path)
            };

            process = new IISExpressProcessEnvelope(Process.Start(info));
        }

        #region IDisposable Members

        public void Dispose()
        {
            process.Dispose();
        }

        #endregion
    }
}
</pre>
</pre>
</div>
<p>Destacando:</p>
<ul>
<li>Faço automação através usando a API do Windows;</li>
<li>Inicio a execução do IISExpress quando a classe é criada e encerro na chamada do Dispose;</li>
<li>Criei um “Envelope” para separar a manipulação do processo da lógica principal.</li>
</ul>
<p>Trata-se de uma solução muito simples. Além disso, sei que o design desse código poderia ser muito melhor. Por isso, <a href="https://gist.github.com/2728219">ele está em um Gist</a>. Adoraria ver sugestões de melhoria.</p>
<h2>Exemplo de uso</h2>
<p>O programa que segue, “levanta” um site na porta 8080. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:e45183d6-623d-47f9-bc05-3deb13845a01" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

namespace Automation.Demo
{
    class Program
    {
        static void Main()
        {
            using (var iis = new IISExpress(8080, @&quot;c:\git\Garbage\WebDirectory\WebDirectory&quot;))
            {
                Console.WriteLine(&quot;Pressione qq tecla para fechar.&quot;);
                Console.ReadLine();
            }

        }
    }
}
</pre>
</pre>
</div>
<p>Bacana, não?! Perceba que não há restrição em quantas aplicações sejam “levantadas” simultaneamente.</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/iis/'>IIS</a>, <a href='http://elemarjr.net/tag/uiautomation/'>UIAutomation</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2801/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2801/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2801/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2801&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/18/promovendo-automao-para-o-iisexpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>
	</item>
		<item>
		<title>FluentCodeMetrics &#8211; Parte 6 &#8211; TypeSets</title>
		<link>http://elemarjr.net/2012/05/17/fluentcodemetrics-parte-6-typesets/</link>
		<comments>http://elemarjr.net/2012/05/17/fluentcodemetrics-parte-6-typesets/#comments</comments>
		<pubDate>Fri, 18 May 2012 01:18:48 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[FluentCodeMetrics]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2798</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Até aqui, calculamos Ce para tipos individualmente. Mas, como proceder para calcular Ce para outras “unidades de análise”. Por exemplo, para um assembly ou namespace. Nesse post, apresento como implementei esse importante avanço no FluentCodeMetrics (veja outros posts relacionados). Lembre-se: todo código-fonte para FluentCodeMetrics está no Github. DISCLAIMER: Adoraria sugestões de [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2798&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Até aqui, calculamos Ce para tipos individualmente. Mas, como proceder para calcular Ce para outras “unidades de análise”. Por exemplo, para um assembly ou namespace.</p>
<p>Nesse post, apresento como implementei esse importante avanço no FluentCodeMetrics (veja <a href="http://elemarjr.net/tag/fluentcodemetrics/">outros posts relacionados</a>).</p>
<p>Lembre-se: todo código-fonte para <a href="https://github.com/ElemarJR/FluentCodeMetrics">FluentCodeMetrics está no Github</a>.</p>
<p><strong><font color="#ff0000">DISCLAIMER: Adoraria sugestões de design. Veja o repositório para entender o projeto e, se possível, me ajude.</font></strong></p>
<h2>Cenários que desejamos implementar</h2>
<p>Basicamente, pretendo implementar dois cenários novos:</p>
<p>1. Desejo poder restringir o cálculo do Ce para referências com tipos de determinados assemblies.</p>
<p>&#160;</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image33.png"><img style="display:block;float:none;margin-left:auto;margin-right:auto;" title="image" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb32.png?w=550&h=236" width="550" height="236" /></a></p>
<p>2. Desejo calcular Ce para um conjunto de tipos, por exemplo, para um assembly/namespace.</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image34.png"><img style="display:block;float:none;margin-left:auto;margin-right:auto;" title="image" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb34.png?w=550&h=229" width="550" height="229" /></a></p>
<p>Pegou a idéia?!</p>
<h2>Filtro de Assembly</h2>
<p>Vamos começar atendendo o primeiro cenário. Começamos com um novo TypeFilter. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4a67040e-dd8c-4f17-9deb-12872470f422" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
using System;
using System.Reflection;

namespace FluentCodeMetrics.Core.TypeFilters
{
    public class FromAssemblyTypeFilter : TypeFilter
    {
        private readonly Assembly assemblyField;

        internal FromAssemblyTypeFilter(Assembly assembly)
        {
            assemblyField = assembly;
        }

        public override bool Check(Type type)
        {
            return type.Assembly == assemblyField;
        }
    }
}
</pre>
</pre>
</div>
<p>Além disso, mudei o TypeFilter (veja o <a href="https://github.com/ElemarJR/FluentCodeMetrics/blob/master/src/FluentCodeMetrics.Core/TypeFilters/TypeFilter.cs">código completo no github</a>) para criar um “method helper”. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:ff5675b1-cf80-4468-a0e0-567728e5d74a" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
public static implicit operator TypeFilter(Assembly assembly)
{
    return FromAssembly(assembly);
}

public static TypeFilter FromAssembly(Assembly assembly)
{
    return new FromAssemblyTypeFilter(assembly);
}
</pre>
</pre>
</div>
<p>Agora, para inferir as Ce para uma classe, apenas considerando referências para tipos do mesmo assembly, basta escrever algo assim:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:b4e761c9-5418-4020-b451-1f838e994ed4" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
Ce.For&lt;Foo&gt;()
    .Ignoring(typeof(Foo).GetType().Assembly.Not());
</pre>
</pre>
</div>
<h2>TypeSet</h2>
<p>Já conseguimos verificar Ce para tipos individuais. Entretanto, muitas vezes, desejaremos trabalhar com um conjunto de tipos (um assembly inteiro, ou um namespace).</p>
<p>Para isso, criei o conceito de TypeSet. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:e3288ac6-2b23-4bbf-b155-95d795eb6e62" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Reflection;
using System.Collections.Generic;

namespace FluentCodeMetrics.Core.TypeSets
{
    public abstract class TypeSet : IEnumerable&lt;Type&gt;
    {
        public abstract IEnumerable&lt;Type&gt; GetAllTypes();

        public IEnumerator&lt;Type&gt; GetEnumerator()
        {
            return GetAllTypes().GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetAllTypes().GetEnumerator();
        }

        public static TypeSet FromAssembly(Assembly assembly)
        {
            return new CollectionTypeSet(assembly.GetTypes());
                // AssemblyTypeSet(assembly);
        }

        public static TypeSet With(params Type[] types)
        {
            return new CollectionTypeSet(types);
        }

        public static implicit operator TypeSet(Assembly source)
        {
            return FromAssembly(source);
        }
    }
}
</pre>
</pre>
</div>
<p>Essa classe base tem uma especialização (por agora). Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:1484cd18-2c2b-4531-b848-b285f80e5f7d" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;

namespace FluentCodeMetrics.Core.TypeSets
{
    public class CollectionTypeSet : TypeSet
    {
        private IEnumerable&lt;Type&gt; source; 
        public CollectionTypeSet(IEnumerable&lt;Type&gt; source)
        {
            this.source = source;
        }

        public override IEnumerable&lt;Type&gt; GetAllTypes()
        {
            return source;
        }
    }
}
</pre>
</pre>
</div>
<p>Aproveitando, também criei um TypeFilter para esse TypeSet. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:ca642e1d-90f5-40fe-8aa7-840c95be748c" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FluentCodeMetrics.Core.TypeFilters
{
    public class CollectionTypeFilter : TypeFilter
    {
        private readonly IEnumerable&lt;Type&gt; typesField;

        internal CollectionTypeFilter(IEnumerable&lt;Type&gt; types)
        {
            typesField = types;
        }

        public override bool Check(Type type)
        {
            return typesField.Contains(type);
        }
    }
}
</pre>
</pre>
</div>
<p>Com mais alguns métodos auxiliares, posso escrever um filtro para diversos tipos dessas duas formas:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:6ebd16ad-2872-4bf4-9d3d-6c79983681f5" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;
using FluentCodeMetrics.Core;
using FluentCodeMetrics.Core.TypeSets;

namespace FluentCodeMetrics.Tests
{
    [TestFixture]
    public class CeTests
    {
        [Test]
        public void Ce_ForSingleArgCtorIgnoringCommonTypes()
        {
            var ce = Ce.For&lt;Samples.SingleArgCtor&gt;()
                .Ignoring&lt;System.Runtime.TargetedPatchingOptOutAttribute&gt;()
                .Ignoring&lt;System.Security.SecuritySafeCriticalAttribute&gt;()
                .Ignoring&lt;System.Runtime.ConstrainedExecution.ReliabilityContractAttribute&gt;()
                .Ignoring&lt;System.Runtime.CompilerServices.CompilerGeneratedAttribute&gt;()
                .Ignoring&lt;System.Object&gt;()
                .Ignoring&lt;System.Int32&gt;()
                .Ignoring&lt;System.String&gt;()
                .Ignoring&lt;System.Boolean&gt;()
                .Ignoring&lt;System.Type&gt;();

            ce.Value.Should().Be(1);
            ce.References.Should().Have.SameValuesAs(
                new[] {typeof (Samples.Fee)}
                );
        }

        [Test]
        public void Ce_ForSingleArgCtorIgnoringTypeSet()
        {
            var ce = Ce.For&lt;Samples.SingleArgCtor&gt;()
                .Ignoring(TypeSet.With(
                    typeof(System.Runtime.TargetedPatchingOptOutAttribute),
                    typeof(System.Security.SecuritySafeCriticalAttribute),
                    typeof(System.Runtime.ConstrainedExecution.ReliabilityContractAttribute),
                    typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute),
                    typeof(object),
                    typeof(int),
                    typeof(string),
                    typeof(bool),
                    typeof(Type)
                ));

            ce.Value.Should().Be(1);
            ce.References.Should().Have.SameValuesAs(
                new[] { typeof(Samples.Fee) }
                );
        }

        [Test]
        public void Ce_ForSingleArgCtorIgnoringOtherAssembliesTypes()
        {
            var ce = Ce.For&lt;Samples.SingleArgCtor&gt;()
                .Ignoring(typeof (Samples.SingleArgCtor).Assembly.Not());
                
            ce.Value.Should().Be(1);
            ce.References.Should().Have.SameValuesAs(
                new[] { typeof(Samples.Fee) }
                );
        }
    }
}
</pre>
</pre>
</div>
<h2>Ce suportando tipos e/ou TypeSets</h2>
<p>Agora temos condições de rever o design do Ce para que este suporte tipos individuais ou conjuntos. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:f47f1b42-39b7-446c-bd3f-4e8a72b444d4" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Linq;

using FluentCodeMetrics.Core.TypeFilters;
using FluentCodeMetrics.Core.TypeSets;
using System.Collections.Generic;

namespace FluentCodeMetrics.Core
{
    public abstract class Ce
    {
        public int Value
        {
            get { return References.Count(); }
        }

        public abstract ReferencedTypesTypeSet References { get; }

        public static implicit operator int(Ce source)
        {
            return source.Value;
        }

        public abstract Ce FilterBy(TypeFilter filter);

        public Ce Ignoring(TypeFilter toIgnore)
        {
            return FilterBy(toIgnore.Not());
        }

        public Ce Ignoring&lt;T&gt;()
        {
            return Ignoring(typeof(T));
        }

        public static TypeSetCe For(TypeSet typeSet)
        {
            var source = from type in typeSet
                         select For(type);

            return new TypeSetCe(source);
        }

        public static TypeCe For(Type type)
        {
            var references = ReferencesInspector.For(type)
                .Where(type.NestedTypes().Not());
            return new TypeCe(references, type);
        }

        public static TypeCe For&lt;T&gt;()
        {
            return For(typeof (T));
        }
    }

   
    public class TypeCe : Ce
    {
        private readonly ReferencedTypesTypeSet references;
        private readonly Type type;
        public Type Type
        {
            get { return type;  }
        }

        internal TypeCe(ReferencedTypesTypeSet refs, Type type)
        {   
            references = refs;
            this.type = type;
        }

        public override ReferencedTypesTypeSet References
        {
            get { return references; }
        }

        public override Ce FilterBy(TypeFilter filter)
        {
            return filter == null ?
                this :
                new TypeCe(references.FilterBy(filter), Type);
        }
    }

    public class TypeSetCe : Ce
    {
        private IEnumerable&lt;Ce&gt; source;

        public IEnumerable&lt;Ce&gt; Source
        {
            get { return source; }
        }

        internal TypeSetCe(IEnumerable&lt;Ce&gt; source)
        {
            this.source = source;
        }
        
        public override ReferencedTypesTypeSet References
        {
            get
            {
                var allReferences = from member in source
                                    from reference in member.References
                                    select reference;
                return new ReferencedTypesTypeSet(allReferences.Distinct(), null);
            }
        }

        public override Ce FilterBy(TypeFilter filter)
        {
            var newSource = source.Select(ceResult =&gt; ceResult.FilterBy(filter)).ToList();
            return new TypeSetCe(newSource);
        }
    }
}
</pre>
</pre>
</div>
<p>Pegou a idéia?!</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/fluentcodemetrics/'>FluentCodeMetrics</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2798/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2798/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2798/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2798&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/17/fluentcodemetrics-parte-6-typesets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb32.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb34.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Primeiros passos com o AutoMapper</title>
		<link>http://elemarjr.net/2012/05/16/promovendo-automao-para-o-iisexpress-2/</link>
		<comments>http://elemarjr.net/2012/05/16/promovendo-automao-para-o-iisexpress-2/#comments</comments>
		<pubDate>Thu, 17 May 2012 02:32:17 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[AutoMapper]]></category>
		<category><![CDATA[Learning Tests]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2791</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Muitas vezes, precisamos “transportar” valores de um objeto (com um tipo) para outro objeto (com outro tipo). Um cenário comum para essa necessidade, é a criação de ViewModels. Essa atividade é conhecida como Mapping. No post de hoje, mostro Learning Tests com AutoMapper – uma bibilieca que facilita muito essa atividade. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2791&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Muitas vezes, precisamos “transportar” valores de um objeto (com um tipo) para outro objeto (com outro tipo). Um cenário comum para essa necessidade, é a criação de ViewModels. Essa atividade é conhecida como Mapping.</p>
<p>No post de hoje, mostro Learning Tests com AutoMapper – uma bibilieca que facilita muito essa atividade.</p>
<p>Como de costume, todo o <a href="https://github.com/ElemarJR/Learning.AutoMapper">código-fonte está no Github</a>.</p>
<h2>O que é o AutoMapper?</h2>
<p>Segundo o <a href="http://automapper.org/">site oficial</a>:</p>
<blockquote><p>AutoMapper is a simple little library built to solve a deceptively complex problem &#8211; getting rid of code that mapped one object to another. This type of code is rather dreary and boring to write, so why not invent a tool to do it for us?</p>
</blockquote>
<p>Seu código-fonte está no <a href="https://github.com/AutoMapper/AutoMapper">Github</a>.</p>
<h2>Referências necessárias</h2>
<p>Mais uma vez, estaremos desenvolvendo Learning Tests. Logo, além da referência para o AutoMapper, adicionamos também referência para o NUnit e para o SharpTestsEx.</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image31.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb30.png?w=554&h=371" width="554" height="371" /></a></p>
<h2>Getting Started</h2>
<p>Comecemos com um exemplo simples.</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:353d1867-22a7-4038-9372-f69a5d2dc6b6" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
using NUnit.Framework;
using SharpTestsEx;

using AutoMapper;

namespace Learning.AutoMapper
{
    [TestFixture]
    public class GettingStarted
    {

        [Test]
        public void MappingIntPropertyToStringProperty()
        {
            Mapper.CreateMap&lt;Foo, Fee&gt;();
            Mapper.AssertConfigurationIsValid();
            
            var source = new Foo {Data = 3};
            var destination = Mapper.Map&lt;Foo, Fee&gt;(source);

            destination.Data.Should().Be(&quot;3&quot;);
        }

        [Test]
        public void MappingStringPropertyToIntProperty()
        {
            Mapper.CreateMap&lt;Fee, Foo&gt;();
            Mapper.AssertConfigurationIsValid();

            var source = new Fee { Data = &quot;3&quot; };
            var destination = Mapper.Map&lt;Fee, Foo&gt;(source);

            destination.Data.Should().Be(3);
        }

        [Test]
        public void MappingStringPropertyToIntProperty_SourceIsNull()
        {
            Mapper.CreateMap&lt;Fee, Foo&gt;();
            Mapper.AssertConfigurationIsValid();

            var source = new Fee { Data = null };
            var destination = Mapper.Map&lt;Fee, Foo&gt;(source);

            destination.Data.Should().Be(0);
        }


        class Foo
        {
            public int Data { get; set; }
        }

        class Fee
        {
            public string Data { get; set; }
        }
    }
}
</pre>
</pre>
</div>
<p>Como pode perceber, há três etapas básicas na utilização AutoMapper:</p>
<ol>
<li><strong>Configuração</strong> – onde especificamos os tipos que desejamos mapear; Isso é feito, geralmente, na inicialização do sistema (ou site); </li>
<li><strong>Verificação</strong> – O método <em>AssertConfigurationIsValid </em>garante que todas as propriedades no tipo “destino” tem um mapeamento para uma fonte de dados do tipo “origem”; </li>
<li><strong>Mapeamento</strong> – Onde ocorre o mapeamento propriamente dito. </li>
</ol>
<p>Perceba que a etapa 2 é opcional. Entretanto, fortemente recomendada.</p>
<p>Repare como o AutoMapper operacionaliza os castings automaticamente.</p>
<h2>Flattening</h2>
<p>Quando estamos trabalhando com ViewModels, geralmente o fazemos por querer trabalhar com modelos mais simples. Veja um exemplo:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:00f28f18-93a2-445c-8be0-c54d0f66f8af" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using NUnit.Framework;
using SharpTestsEx;

using AutoMapper;

namespace Learning.AutoMapper
{
    [TestFixture]
    public class FlatteningSimple
    {
        [Test]
        public void HierarchyToFlattenObject()
        {
            Mapper.CreateMap&lt;Person, PersonFlat&gt;();
            Mapper.AssertConfigurationIsValid();

            var source = new Person
            {
                Name = &quot;Elemar Junior&quot;,
                Address = new Address
                {
                    Street = &quot;St. Francis&quot;,
                    Number = 1024
                }
            };

            var destination = Mapper.Map&lt;Person, PersonFlat&gt;(source);

            destination.Name.Should().Be(source.Name);
            destination.AddressStreet.Should().Be(source.Address.Street);
            destination.AddressNumber.Should().Be(source.Address.Number);
            destination.Salary.Should().Be(source.GetSalary());
        }


        class Address
        {
            public string Street { get; set; }
            public int Number { get; set; }
        }

        class Person
        {
            public string Name { get; set; }
            public Address Address { get; set; }
            public decimal GetSalary()
            {
                return 25;
            }
        }

        class PersonFlat
        {
            public string Name { get; set; }
            public string AddressStreet { get; set; }
            public int AddressNumber { get; set; }
            public decimal Salary { get; set; }
        }
    }
}
</pre>
</pre>
</div>
<p>O AutoMapper reconhece os mapeamentos automaticamente em função do “regramento” no nome das propriedades.</p>
<h2>Nesting Mapping</h2>
<p>As vezes, queremos aplicar mapping em objetos filhos. Com AutoMapper isso é muito simples. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:8bfc3b10-f333-431c-900e-a64113250348" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using AutoMapper;

namespace Learning.AutoMapper
{
    [TestFixture]
    public class NestedMappings
    {
        [Test]
        public void SrcToDst()
        {
            Mapper.CreateMap&lt;SrcParent, DstParent&gt;();
            Mapper.CreateMap&lt;SrcChild, DstChild&gt;();
            Mapper.AssertConfigurationIsValid();

            var source = new SrcParent()
            {
                Value = 3,
                Child = new SrcChild
                {
                    AnotherValue = 4
                }
            };

            var dest = Mapper.Map&lt;SrcParent, DstParent&gt;(source);
            dest.Value.Should().Be(source.Value);
            dest.Child.AnotherValue.Should().Be(
                source.Child.AnotherValue
                );
        }

        class SrcParent
        {
            public int Value { get; set; }
            public SrcChild Child { get; set; }
        }

        class SrcChild
        {
            public int AnotherValue { get; set; }
        }

        class DstParent
        {
            public int Value { get; set; }
            public DstChild Child { get; set; }
        }

        class DstChild
        {
            public int AnotherValue { get; set; }
        }
        
    }
}
</pre>
</pre>
</div>
<h2>Quando o Mapping automático não atende</h2>
<p>Nem sempre teremos equivalência/compatibilidade de nomes nos objetos de origem e destino. Nesse caso, AutoMapper nos oferece algumas alteranativas. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:f691e7d1-705d-4780-bcfd-b77e5a0229d6" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using NUnit.Framework;
using SharpTestsEx;

using AutoMapper;

namespace Learning.AutoMapper
{
    [TestFixture]
    public class CustomResolver
    {
        [Test]
        public void SummarizeUsingCustomResolver()
        {
            Mapper.CreateMap&lt;Src, Dst&gt;()
                .ForMember(dst =&gt; dst.Total, opt =&gt; opt.ResolveUsing&lt;TotalResolver&gt;());

            Mapper.AssertConfigurationIsValid();

            var source = new Src {Value1 = 10, Value2 = 15};
            var dest = Mapper.Map&lt;Src, Dst&gt;(source);

            dest.Total.Should().Be(source.Value1 + source.Value2);
        }

        [Test]
        public void SummarizeUsingMapFrom()
        {
            Mapper.CreateMap&lt;Src, Dst&gt;()
                .ForMember(dst =&gt; dst.Total, opt =&gt; opt.MapFrom(src =&gt; src.Value1 + src.Value2));

            Mapper.AssertConfigurationIsValid();

            var source = new Src { Value1 = 10, Value2 = 15 };
            var dest = Mapper.Map&lt;Src, Dst&gt;(source);

            dest.Total.Should().Be(source.Value1 + source.Value2);
        }

        class TotalResolver : ValueResolver&lt;Src, int&gt;
        {
            protected override int ResolveCore(Src source)
            {
                return source.Value1 + source.Value2;
            }
        }

        class Src
        {
            public int Value1 { get; set; }
            public int Value2 { get; set; }
        }

        class Dst
        {
            public int Total { get; set; }
        }
    }
}
</pre>
</pre>
</div>
<p>Acho que o código é auto-explicativo.</p>
<h2>Concluindo…</h2>
<p>Vejamos os testes:</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image32.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb31.png?w=554&h=343" width="554" height="343" /></a></p>
<p>AutoMapper ainda oferece recursos mais avançados, apropriados para cenários mais complexos. Mas, acho que o que mostrei aqui já cobre boa parte dos cenários de uso.</p>
<p>De qualquer forma, o código está no github. Qualquer coisa, dá um fork e amplia o projeto.</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/automapper/'>AutoMapper</a>, <a href='http://elemarjr.net/tag/learning-tests/'>Learning Tests</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2791/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2791/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2791/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2791&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/16/promovendo-automao-para-o-iisexpress-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb30.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb31.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Vou palestrar no MSDN Community BluDotNet</title>
		<link>http://elemarjr.net/2012/05/15/vou-palestrar-no-msdn-community-bludotnet/</link>
		<comments>http://elemarjr.net/2012/05/15/vou-palestrar-no-msdn-community-bludotnet/#comments</comments>
		<pubDate>Wed, 16 May 2012 01:12:09 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[Aviso]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2785</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Tive a honra de ser convidado para palestrar em um evento organizado pela comunidade BluDotNet, em Blumenau. Será o MSDN Community BluDotNet. Ocorrerá no dia 23 de junho, sábado, no SENAI de Blumenau. Inscrições serão abertas em breve. Será muito bacana conversar e compartilhar conhecimentos com vocês. Tagged: Aviso<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2785&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Tive a honra de ser convidado para palestrar em um evento organizado pela <a href="http://www.bludotnet.com.br/">comunidade BluDotNet</a>, em Blumenau.</p>
<p>Será o <a href="http://www.bludotnet.com.br/eventos-2/?event_id=17">MSDN Community BluDotNet</a>. Ocorrerá no dia 23 de junho, sábado, no SENAI de Blumenau.</p>
<p>Inscrições serão abertas em breve. </p>
<p>Será muito bacana conversar e compartilhar conhecimentos com vocês.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/aviso/'>Aviso</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2785/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2785/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2785/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2785&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/15/vou-palestrar-no-msdn-community-bludotnet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>
	</item>
		<item>
		<title>Facilitando inje&#231;&#227;o de depend&#234;ncia com Ninject!</title>
		<link>http://elemarjr.net/2012/05/15/facilitando-injeo-de-dependncia-com-ninject/</link>
		<comments>http://elemarjr.net/2012/05/15/facilitando-injeo-de-dependncia-com-ninject/#comments</comments>
		<pubDate>Wed, 16 May 2012 00:18:11 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[DI]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Learning Tests]]></category>
		<category><![CDATA[Ninject]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2783</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Reduzir o acoplamento é fundamental para melhorar a qualidade do design de nossas aplicações. Uma das formas mais diretas de promover a redução de acoplamento éatravés&#160; a injeção de dependências (DI) e da inversão do controle (IoC). Nesse post, apresento uma série de learning testes para o Ninject – um popular [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2783&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Reduzir o acoplamento é fundamental para melhorar a qualidade do design de nossas aplicações. Uma das formas mais diretas de promover a redução de acoplamento éatravés&#160; a injeção de dependências (DI) e da inversão do controle (IoC).</p>
<p>Nesse post, apresento uma série de learning testes para o Ninject – um popular framework de injeção de dependências para .net. Será um post com “mais código e menos conversa”.</p>
<p>Todo o código-fonte desenvolvido está em um <a href="https://github.com/ElemarJR/Learning.Ninject">repositório no Github</a>.</p>
<h2>O que é Ninject? </h2>
<p>Segundo o <a href="http://www.ninject.org/">site oficial</a>:</p>
<blockquote><p>Ninject is a lightweight dependency injection framework for .NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software’s architecture, your code will become easier to write, reuse, test, and modify.</p>
</blockquote>
<p>O código-fonte do Ninject está no <a href="https://github.com/ninject/ninject">Github</a>.</p>
<h2>Para aprender mais sobre DI e Ninject</h2>
<p>Ninject possui uma excelente <a href="http://www.ninject.org/wiki.html">documentação online</a> (o que é raro em projetos FOSS). Lá é possível aprender Ninject e conceitos fundamentais sobre DI. </p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image29.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb28.png?w=333&h=304" width="333" height="304" /></a></p>
<h2>Referências</h2>
<p>Mais uma vez, estaremos desenvolvendo um Learning Test. Logo, além da referência para o Ninject, adicionamos também referência para o NUnit e para o SharpTestsEx. </p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image30.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb29.png?w=550&h=364" width="550" height="364" /></a></p>
<h2>Getting Started</h2>
<p>Referências adicionadas, hora de por as “mãos na massa”. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:1856bbd7-5973-4157-b4d1-78c89dc7b91e" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;


namespace Learning.Ninject
{
    [TestFixture]
    public class GettingStarted
    {
       
        [Test]
        public void BindIFooToFoo_GettingIFoo_ReturnsFooInstance()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(typeof (Foo));
        }

        [Test]
        public void BindIFooToFee_GettingIFoo_ReturnsFeeInstance()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(typeof(Fee));
        }

        [Test]
        [TestCase(typeof(IFoo), typeof(Foo))]
        [TestCase(typeof(IFoo), typeof(Fee))]
        public void BindingInterfaceToType_GettingInterface_ReturnsTypeInstance
            (Type @interface, Type concreteType)
        {
            var kernel = new StandardKernel();

            kernel
                .Bind(@interface).To(concreteType);

            var result = kernel.Get(@interface);

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(concreteType);            
        }
    }

    public interface IFoo
    {
        string GetMessage();
    }

    class Foo : IFoo
    {
        public string GetMessage()
        {
            return "Hello from Foo";
        }
    }

    class Fee : IFoo
    {
        public string GetMessage()
        {
            return "Hello from Fee";
        }
    }
}
</pre>
</pre>
</div>
<p>Aqui você pega a essência do Ninject. Basicamente:</p>
<ul>
<li>Criamos um “kernel” que será o objeto responsável por “resolver” instâncias para os tipos que especificarmos;</li>
<li>Associamos implementações concretas para tipos (geralmente abstratos ou interfaces) que desejaremos resolver;</li>
<li>Usamos o “kernel” para carregar as instâncias.</li>
</ul>
<h2>Injetando dependências na inicialização</h2>
<p>Com um Kernel configurado, podemos injetar dependências em nossos objetos de forma muito simples. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:4dbf1bc2-a763-4dda-8bcc-1289c741ce62" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;


namespace Learning.Ninject
{
    [TestFixture]
    public class Initialization
    {

        [Test]
        public void SingleCtor()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.Source.GetType().Should().Be(typeof(Fee));
        }

        [Test]
        public void TwoCtors()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            kernel
                .Bind().ToSelf();

            var result = kernel.Get();


            result.Should().Not.Be.Null();
            result.Source.GetType().Should().Be(typeof(Fee));
        }
    }

    public class Writer
    {
        public readonly IFoo Source;
        public Writer(IFoo source)
        {
            Source = source;
        }
    }

    public class Writer2
    {
        public readonly IFoo Source;
        [Inject]
        public Writer2(IFoo source)
        {
            Source = source;
        }

        public Writer2(Writer writer)
        {
            throw new NotImplementedException();
        }
    }
}
</pre>
</pre>
</div>
<p>Repare que Ninject consegue “fornecer” valores adequados, especificados no construtor com mais argumentos, de acordo com os bindings que foram informados.</p>
<p>Repare também que quando há um “empate” entre construtores, resolvemos a “dúvidas” marcando o construtor “default” com o atributo Inject.</p>
<h2>Injetando dependências através de métodos ou propriedades</h2>
<p>Nem todas as dependências precisam estar explicitadas no consrutor. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:cc67697f-fe89-4d43-a95e-1577e5fc9491" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;


namespace Learning.Ninject
{
    [TestFixture]
    public class PropertyMethodInjection
    {

        [Test]
        public void PropertyInjection()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            var result = kernel.Get();
            result.FooInstance.Should().Not.Be.Null();
            result.FooInstance.GetType().Should().Be(typeof(Fee));
        }

        [Test]
        public void MethodInjection()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To();

            var result = kernel.Get();
            result.GetDataType().Should().Be(typeof(Fee));
        }
    }

   class FooPropertyInjection
   {
       [Inject]
       public IFoo FooInstance { get; set; }
   }

    class FooMethodInjection
    {
        private IFoo data;

        [Inject]
        public void SetData(IFoo data)
        {
            this.data = data;
        }

        public Type GetDataType()
        {
            return data.GetType();
        }
    }
}
</pre>
</pre>
</div>
<p>Como pode ver, basta marcar métodos ou propriedades para injeção de dependência com o atributo Inject.</p>
<h2>Singleton</h2>
<p>Todo mundo que começa lê o livro do GoF, pega uma doença: Singletite. Veja a versão Ninject dessa doença:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:91bf9de6-3010-4a1f-b571-319da930be4e" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;


namespace Learning.Ninject
{
    [TestFixture]
    public class Singleton
    {

        [Test]
        public void BindIFooToFooInSingletonScope_GettingIFooTwoTimes_ReturnsSameFooInstance()
        {
            var kernel = new StandardKernel();

            kernel
                .Bind().To().InSingletonScope();

            var resultA = kernel.Get();
            var resultB = kernel.Get();

            resultA.Should().Not.Be.Null();
            resultB.Should().Not.Be.Null();
            resultA.Should().Be.SameInstanceAs(resultB);
        }

        [Test]
        public void BindIFooToFooInstance_GettingIFooTwoTimes_ReturnsSameFooInstance()
        {
            var kernel = new StandardKernel();

            var source = new Foo();

            kernel
                .Bind().ToConstant(source);

            var resultA = kernel.Get();
            var resultB = kernel.Get();

            resultA.Should().Not.Be.Null();
            resultB.Should().Not.Be.Null();
            resultA.Should().Be.SameInstanceAs(resultB);
            source.Should().Be.SameInstanceAs(resultA);
        }
    }
}
</pre>
</pre>
</div>
<h2>Organizando a inicialização do Ninject usando módulos</h2>
<p>Em uma aplicação real, é sempre uma boa prática organizar a inicialização do Ninject em uma “módulo”. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:ba657a3d-601f-4ca8-98e2-27f268fd14d3" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;
using Ninject.Modules;


namespace Learning.Ninject
{
    [TestFixture]
    public class Modules
    {
        [Test]
        public void BindIFooToFooUsingModules_GettingIFoo_ReturnsFooInstance()
        {
            var kernel = new StandardKernel(new LearningTestModule());

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(typeof (Foo));
        }
    }

    public class LearningTestModule : NinjectModule
    {
        public override void Load()
        {
            Bind().To();
        }
    }

}
</pre>
</pre>
</div>
<p>Pegou a idéia, certo?!</p>
<h2>Personalizando a inicialização de instâncias através de Providers</h2>
<p>As vezes, a inicialização de objetos pode exigir um processo mais complexo. Para isso, podemos usar providers. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:7560fd54-52c5-4540-88ec-8059310cbcff" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;

using NUnit.Framework;
using SharpTestsEx;

using Ninject;
using Ninject.Activation;


namespace Learning.Ninject
{
    [TestFixture]
    public class Providers
    {
        [Test]
        public void BindIFooToFooUsingProvider_GettingIFoo_ReturnsFooInstance()
        {
            var kernel = new StandardKernel();
            kernel.Bind().ToProvider(new FooProvider());

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(typeof (Foo));
        }

        [Test]
        public void BindIFooToFooUsingMethod_GettingIFoo_ReturnsFooInstance()
        {
            var kernel = new StandardKernel();
            kernel.Bind().ToMethod(context =&gt; new Fee());

            var result = kernel.Get();

            result.Should().Not.Be.Null();
            result.GetType().Should().Be(typeof(Fee));
        }
    }

    class FooProvider : Provider
    {
        protected override IFoo CreateInstance(IContext context)
        {
            return new Foo();
        }
    }

}
</pre>
</pre>
</div>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/di/'>DI</a>, <a href='http://elemarjr.net/tag/ioc/'>IoC</a>, <a href='http://elemarjr.net/tag/learning-tests/'>Learning Tests</a>, <a href='http://elemarjr.net/tag/ninject/'>Ninject</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2783/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2783/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2783/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2783&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/15/facilitando-injeo-de-dependncia-com-ninject/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb28.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb29.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Primeiros passos com Apache log4net</title>
		<link>http://elemarjr.net/2012/05/14/primeiros-passos-com-apache-log4net/</link>
		<comments>http://elemarjr.net/2012/05/14/primeiros-passos-com-apache-log4net/#comments</comments>
		<pubDate>Tue, 15 May 2012 02:29:22 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[Learning Tests]]></category>
		<category><![CDATA[log4net]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2776</guid>
		<description><![CDATA[Olá pessoal. Tudo certo?! Em muitos cenários, ter uma implementação efetiva de logging em nossas aplicações pode acelerar consideravelmente processos de depuração e/ou apoio ao cliente. Implementar logging é uma tarefa relativamente simples. Entrentanto, trabalhosa. Além disso, é relativamente fácil implementar a “coisa errada”, causando prejuízo a performance do sistema. No post de hoje, mostro [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2776&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Tudo certo?!</p>
<p>Em muitos cenários, ter uma implementação efetiva de logging em nossas aplicações pode acelerar consideravelmente processos de depuração e/ou apoio ao cliente.</p>
<p>Implementar logging é uma tarefa relativamente simples. Entrentanto, trabalhosa. Além disso, é relativamente fácil implementar a “coisa errada”, causando prejuízo a performance do sistema.</p>
<p>No post de hoje, mostro os conceitos fundamentais do <a href="http://logging.apache.org/log4net/">log4net</a>. Uma biblioteca poderosa para logging.</p>
<p>Todo o <a href="https://github.com/ElemarJR/Learning.Log4Net">código-fonte desenvolvido hoje está no meu github</a>. </p>
<h2>O que é log4net?</h2>
<p>Segundo o <a href="http://logging.apache.org/log4net/">site oficial</a>: </p>
<blockquote><p>The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets. log4net is a port of the excellent Apache log4j™ framework to the Microsoft® .NET runtime. We have kept the framework similar in spirit to the original log4j while taking advantage of new features in the .NET runtime.</p>
</blockquote>
<p>Trata-se de um projeto FOSS. Há um mirror de seu código-fonte no <a href="https://github.com/apache/log4net">github</a>.</p>
<h2>Lógica de funcionamento</h2>
<p>Para saber usar log4net, é importante entender seu modelo básico de funcionamento:</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image27.png"><img style="display:block;float:none;margin-left:auto;margin-right:auto;" title="image" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb26.png?w=550&h=319" width="550" height="319" /></a></p>
<p>&#160;</p>
<p>Para entender:</p>
<ul>
<li><strong><em>Logger</em></strong> – é a “interface” principal com o nosso código. Quando desejemos que alguma coisa entre no log, é para esse objto que enviamos mensagens; </li>
<li><strong><em>Appender</em></strong> – é o responsável por “publicar” as informações enviadas para o logger. Um logger pode ter um ou vários appenders associados; </li>
<li><strong><em>Filter</em></strong> – é usado para analisar a informação enviada ao logger e decidir se esta deverá ou não ser processada pelo appender. Um appender pode ter vários filters associados. Uma informação só será processada pelo appender se for “aprovada” for todos os filter;</li>
<li><strong><em>Layout</em></strong> – &quot;formata” a informação enviada ao logger em diferentes estilos. </li>
<li><strong><em>ObjectRenderer</em></strong> – é uma espécie de “converter” para string de objetos.</li>
</ul>
<p>log4net é extremamente flexíbel por permitir o ajuste fino de todos esses componentes. Isso pode ser feito tanto em código quanto em arquivos de configuração.</p>
<h2>Referências necessárias</h2>
<p>log4net possui pacote no GitHub. </p>
<p>Para o post de hoje, utilizei esse pacote junto com NUnit e sharpTestsEx. Veja:</p>
<p><a href="http://elemarjr.files.wordpress.com/2012/05/image28.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;border-top:0;margin-right:auto;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://elemarjr.files.wordpress.com/2012/05/image_thumb27.png?w=554&h=371" width="554" height="371" /></a></p>
<h2>Dois <strong><em>appenders </em></strong>para teste</h2>
<p>Aproveitando a flexibilidade do log4net, desenvolvi dois appenders para facilitar testes. Em cenários reais, isso não seria necessário. log4net já possui um conjunto rico de appenders que permite, entre outras coisas: emitir informações no console, salvar informações em banco de dados, em arquivos texto e xml.</p>
<p>O primeiro appender que desenvolvi simplesmente acumula as informações em um StringBuilder. Veja:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:40c4ea76-8513-47ab-a2bf-c07c7387fd3e" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp; pad-line-numbers: true;">
using System.Text;

using log4net.Appender;
using log4net.Core;

namespace Learning.Log4Net.Appenders
{
    class StringAppender : AppenderSkeleton
    {
        private readonly StringBuilder buffer =
            new StringBuilder();

        public void Reset()
        {
            buffer.Length = 0;
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            buffer.Append(RenderLoggingEvent(loggingEvent));
        }

        protected override bool RequiresLayout
        {
            get
            { return true; }
        }

        public override string ToString()
        {
            return buffer.ToString();
        }
    }
}
</pre>
</pre>
</div>
<p>Como pode ver, criar um Appender não é tarefa das mais difíceis. Abaixo, um appender que, simplesmente, conta a quantidade de vezes que é chamado.</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:ff4d5ead-97ed-4a9a-b884-a38d32dc0f90" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using log4net.Appender;
using log4net.Core;

namespace Learning.Log4Net.Appenders
{
    public class CountingAppender : AppenderSkeleton
    {
        private int counter;

        public int Counter
        {
            get { return counter; }
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            counter++;
        }
    }
}
</pre>
</pre>
</div>
<h2>Getting Started</h2>
<p>Para que você possa entender o funcionamento do log4net, considere os testes que seguem:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:a28712e7-420e-44e7-a643-fc92d45923ed" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using Learning.Log4Net.Appenders;
using NUnit.Framework;
using SharpTestsEx;
using log4net;
using log4net.Config;
using log4net.Layout;

namespace Learning.Log4Net
{
    [TestFixture]
    public class GettingStarted
    {
        #region Setup/Teardown

        [SetUp]
        public void SetUp()
        {
            stringAppender = new StringAppender
            {
                Layout = new PatternLayout(&quot;%level - %message&quot;)
            };

            BasicConfigurator.Configure(stringAppender);
            log = LogManager.GetLogger(typeof (GettingStarted));

            log.Should().Not.Be.Null();
        }

        [TearDown]
        public void TearDown()
        {
            LogManager.GetRepository().ResetConfiguration();
            LogManager.GetRepository().Shutdown();
            ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear();
        }

        #endregion

        private ILog log;
        private StringAppender stringAppender;

        [Test]
        public void LogDebug()
        {
            const string msg = &quot;Hello Log4Net, Debug&quot;;
            log.Debug(msg);
            stringAppender.ToString().Should()
                .Be(&quot;DEBUG - &quot; + msg);
        }

        [Test]
        public void LogDebugFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Debug&quot;;
            log.DebugFormat(pattern, &quot;Log4Net&quot;, &quot;Debug&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;DEBUG - &quot; + expected);
        }

        [Test]
        public void LogError()
        {
            const string msg = &quot;Hello Log4Net, Error&quot;;
            log.Error(msg);
            stringAppender.ToString().Should()
                .Be(&quot;ERROR - &quot; + msg);
        }

        [Test]
        public void LogErrorFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Error&quot;;
            log.ErrorFormat(pattern, &quot;Log4Net&quot;, &quot;Error&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;ERROR - &quot; + expected);
        }

        [Test]
        public void LogFatal()
        {
            const string msg = &quot;Hello Log4Net, Fatal&quot;;
            log.Fatal(msg);
            stringAppender.ToString().Should()
                .Be(&quot;FATAL - &quot; + msg);
        }

        [Test]
        public void LogFatalFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Fatal&quot;;
            log.FatalFormat(pattern, &quot;Log4Net&quot;, &quot;Fatal&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;FATAL - &quot; + expected);
        }

        [Test]
        public void LogInfo()
        {
            const string msg = &quot;Hello Log4Net, Info&quot;;
            log.Info(msg);
            stringAppender.ToString().Should()
                .Be(&quot;INFO - &quot; + msg);
        }

        [Test]
        public void LogInfoFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Info&quot;;
            log.InfoFormat(pattern, &quot;Log4Net&quot;, &quot;Info&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;INFO - &quot; + expected);
        }

        [Test]
        public void LogWarn()
        {
            const string msg = &quot;Hello Log4Net, Warn&quot;;
            log.Warn(msg);
            stringAppender.ToString().Should()
                .Be(&quot;WARN - &quot; + msg);
        }

        [Test]
        public void LogWarnFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Warn&quot;;
            log.WarnFormat(pattern, &quot;Log4Net&quot;, &quot;Warn&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;WARN - &quot; + expected);
        }
    }
}
</pre>
</pre>
</div>
<p>A rotina de TearDown é importante apenas para cenários de teste. Não é necessário que você conheça o processo no seu dia-a-dia.</p>
<p>Vamos ver a inicialização:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:ffd8bcc6-f718-4823-9952-9c33a300d8c8" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
[SetUp]
public void SetUp()
{
    stringAppender = new StringAppender
    {
        Layout = new PatternLayout(&quot;%level - %message&quot;)
    };

    BasicConfigurator.Configure(stringAppender);
    log = LogManager.GetLogger(typeof (GettingStarted));

    log.Should().Not.Be.Null();
}
</pre>
</pre>
</div>
<p>A configuração do appender a utilizar, bem como o Layout geralmente é feita no App.Config (veja o site <a href="http://logging.apache.org/log4net/release/config-examples.html">oficial para ver exemplos efetivos</a>). A linha importante aqui é a que carrega o logger (usando o objeto estático LogManager).</p>
<p>Como você pode ver, log4net ofecere cinco níveis diferentes de log: debug, info, warn, error, fatal.</p>
<p>Esses cinco níveis podem ser utilizados, entre outras coisas, como um primeiro filtro do que deve ser exibido. Além disso, podem receber formatação diferente.</p>
<p>Para ver um uso mais “prático” desses níveis, veja um exemplo fornecido pelo próprio log4net.</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:006626b2-2e31-4291-b220-7496028a2cf4" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
// This will cause log4net to look for a configuration file
// called ConsoleApp.exe.config in the application base
// directory (i.e. the directory containing ConsoleApp.exe)

namespace ConsoleApp
{
	using System;

	/// &lt;summary&gt;
	/// Example of how to simply configure and use log4net
	/// &lt;/summary&gt;
	public class LoggingExample
	{
		// Create a logger for use in this class
		private static readonly log4net.ILog log = 
			log4net.LogManager.GetLogger(
				System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
			);
		// NOTE that using System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
		// is equivalent to typeof(LoggingExample) but is more portable
		// i.e. you can copy the code directly into another class without
		// needing to edit the code.

		/// &lt;summary&gt;
		/// Application entry point
		/// &lt;/summary&gt;
		/// &lt;param name=&quot;args&quot;&gt;command line arguments&lt;/param&gt;
		public static void Main(string[] args)
		{
			// Log an info level message
			if (log.IsInfoEnabled) log.Info(&quot;Application [ConsoleApp] Start&quot;);

			// Log a debug message. Test if debug is enabled before
			// attempting to log the message. This is not required but
			// can make running without logging faster.
			if (log.IsDebugEnabled) log.Debug(&quot;This is a debug message&quot;);

			try
			{
				Bar();
			}
			catch(Exception ex)
			{
				// Log an error with an exception
				log.Error(&quot;Exception thrown from method Bar&quot;, ex);
			}

			log.Error(&quot;Hey this is an error!&quot;);

			// Push a message on to the Nested Diagnostic Context stack
			using(log4net.NDC.Push(&quot;NDC_Message&quot;))
			{
				log.Warn(&quot;This should have an NDC message&quot;);

				// Set a Mapped Diagnostic Context value  
				log4net.MDC.Set(&quot;auth&quot;, &quot;auth-none&quot;);
				log.Warn(&quot;This should have an MDC message for the key 'auth'&quot;);

			} // The NDC message is popped off the stack at the end of the using {} block

			log.Warn(&quot;See the NDC has been popped of! The MDC 'auth' key is still with us.&quot;);

			// Log an info level message
			if (log.IsInfoEnabled) log.Info(&quot;Application [ConsoleApp] End&quot;);

			Console.Write(&quot;Press Enter to exit...&quot;);
			Console.ReadLine();
		}

		// Helper methods to demonstrate location information and nested exceptions

		private static void Bar()
		{
			Goo();
		}

		private static void Foo()
		{
			throw new Exception(&quot;This is an Exception&quot;);
		}

		private static void Goo()
		{
			try
			{
				Foo();
			}
			catch(Exception ex)
			{
				throw new ArithmeticException(&quot;Failed in Goo. Calling Foo. Inner Exception provided&quot;, ex);
			}
		}
	}
}
</pre>
</pre>
</div>
<p>Acho que você pegou a idéia.</p>
<h2>Entendendo Levels</h2>
<p>Os “levels” do log4net são extremamente importantes e servem como um primeiro filtro sobre o que deve, ou não, ser considerado pelo appender. Veja isso no seguinte bloco de testes:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:f67a7789-8663-49a2-b3ab-0b46e489ca65" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using NUnit.Framework;
using SharpTestsEx;

using Learning.Log4Net.Appenders;
using log4net.Config;
using log4net;
using log4net.Core;
using log4net.Appender;

namespace Learning.Log4Net
{
    [TestFixture]
    public class Levels
    {
        [SetUp]
        public void SetUp()
        {
            appender = new CountingAppender();
            BasicConfigurator.Configure(appender);
            log = LogManager.GetLogger(typeof (GettingStarted));

            log.Should().Not.Be.Null();
        }

        [TearDown]
        public void TearDown()
        {
            LogManager.GetRepository().ResetConfiguration();
            LogManager.GetRepository().Shutdown();
            ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear();
        }

        private ILog log;
        private CountingAppender appender;
        [Test]
        [TestCase(&quot;All&quot;, 5)]
        [TestCase(&quot;Debug&quot;, 5)]
        [TestCase(&quot;Info&quot;, 4)]
        [TestCase(&quot;Warn&quot;, 3)]
        [TestCase(&quot;Error&quot;, 2)]
        [TestCase(&quot;Fatal&quot;, 1)]
        [TestCase(&quot;Off&quot;, 0)]
        public void TestLevel(string level, int expectedCount)
        {
            //(Level)Enum.Parse(typeof (Level), &quot;All&quot;);
            var l = (Level) typeof (Level).GetField(level).GetValue(null);
            appender.Threshold = l;
            log.Debug(&quot;&quot;);
            log.Info(&quot;&quot;);
            log.Warn(&quot;&quot;);
            log.Error(&quot;&quot;);
            log.Fatal(&quot;&quot;);
            appender.Counter.Should().Be(expectedCount);
        }
    }
}
</pre>
</pre>
</div>
<p>Pegou a ideia? Debug &lt; Info &lt; Warn &lt; Error &lt; Fatal.</p>
<h2>Usando arquivos de configuração</h2>
<p>log4net pode ser facilmente configurado através de arquivos xml. Veja um exemplo de arquivo de configuração:</p>
<div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:3b2116c8-9e12-4d00-8bea-b9c7f5d25a17" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;log4net&gt;
  &lt;appender name=&quot;stringAppender&quot; type=&quot;Learning.Log4Net.Appenders.StringAppender, Learning.Log4Net&quot;&gt;
    &lt;layout type=&quot;log4net.Layout.PatternLayout&quot;&gt;
      &lt;conversionPattern value=&quot;%level - %message&quot; /&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;

  &lt;appender name=&quot;consoleAppender&quot; type=&quot;log4net.Appender.ConsoleAppender&quot;&gt;
    &lt;layout type=&quot;log4net.Layout.PatternLayout&quot;&gt;
      &lt;conversionPattern value=&quot;%level - %message%newline&quot; /&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;
  
  &lt;root&gt;
    &lt;level value=&quot;ALL&quot; /&gt;
    &lt;appender-ref ref=&quot;stringAppender&quot; /&gt;
    &lt;appender-ref ref=&quot;consoleAppender&quot; /&gt;
  &lt;/root&gt;
&lt;/log4net&gt;

</pre>
</pre>
</div>
<p>Esse esquema é semelhante ao que seria utilizado no app.config. Abaixo, uma versão modificada do primeiro bloco de testes que carrega esse arquivo. Veja:</p>
<p><div style="margin:0;display:inline;float:none;padding:0;" id="scid:C89E2BDB-ADD3-4f7a-9810-1B7EACF446C1:15f05627-355f-4dfd-9452-c623232fac9c" class="wlWriterEditableSmartContent">
<pre style="white-space:normal;">
<pre class="brush: csharp;">
using System;
using System.Xml;
using NUnit.Framework;
using SharpTestsEx;
using log4net;
using log4net.Config;
using log4net.Layout;
using log4net.Repository;
using log4net.Appender;

namespace Learning.Log4Net
{
    [TestFixture]
    public class ConfigUsingXml
    {
        #region Setup/Teardown

        [SetUp]
        public void SetUp()
        {
            var log4NetConfig = new XmlDocument();
            
            log4NetConfig.Load(@&quot;ConfigSamples\config-01.xml&quot;);
            
            ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
            XmlConfigurator.Configure(rep, log4NetConfig[&quot;log4net&quot;]);

            var appenders = LogManager.GetRepository(rep.Name).GetAppenders();
            appenders.Length.Should().Be(2);

            stringAppender = appenders[0];

            log = LogManager.GetLogger(rep.Name, typeof (ConfigUsingXml));
            log.Should().Not.Be.Null();
        }

        [TearDown]
        public void TearDown()
        {
            LogManager.GetRepository().ResetConfiguration();
            LogManager.GetRepository().Shutdown();
            ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Clear();
        }

        #endregion

        private ILog log;
        private IAppender stringAppender;

        [Test]
        public void LogDebug()
        {
            const string msg = &quot;Hello Log4Net, Debug&quot;;
            log.Debug(msg);
            stringAppender.ToString().Should()
                .Be(&quot;DEBUG - &quot; + msg);
        }

        [Test]
        public void LogDebugFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Debug&quot;;
            log.DebugFormat(pattern, &quot;Log4Net&quot;, &quot;Debug&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;DEBUG - &quot; + expected);
        }

        [Test]
        public void LogError()
        {
            const string msg = &quot;Hello Log4Net, Error&quot;;
            log.Error(msg);
            stringAppender.ToString().Should()
                .Be(&quot;ERROR - &quot; + msg);
        }

        [Test]
        public void LogErrorFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Error&quot;;
            log.ErrorFormat(pattern, &quot;Log4Net&quot;, &quot;Error&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;ERROR - &quot; + expected);
        }

        [Test]
        public void LogFatal()
        {
            const string msg = &quot;Hello Log4Net, Fatal&quot;;
            log.Fatal(msg);
            stringAppender.ToString().Should()
                .Be(&quot;FATAL - &quot; + msg);
        }

        [Test]
        public void LogFatalFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Fatal&quot;;
            log.FatalFormat(pattern, &quot;Log4Net&quot;, &quot;Fatal&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;FATAL - &quot; + expected);
        }

        [Test]
        public void LogInfo()
        {
            const string msg = &quot;Hello Log4Net, Info&quot;;
            log.Info(msg);
            stringAppender.ToString().Should()
                .Be(&quot;INFO - &quot; + msg);
        }

        [Test]
        public void LogInfoFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Info&quot;;
            log.InfoFormat(pattern, &quot;Log4Net&quot;, &quot;Info&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;INFO - &quot; + expected);
        }

        [Test]
        public void LogWarn()
        {
            const string msg = &quot;Hello Log4Net, Warn&quot;;
            log.Warn(msg);
            stringAppender.ToString().Should()
                .Be(&quot;WARN - &quot; + msg);
        }

        [Test]
        public void LogWarnFormat()
        {
            const string pattern = &quot;Hello {0}, {1}&quot;;
            const string expected = &quot;Hello Log4Net, Warn&quot;;
            log.WarnFormat(pattern, &quot;Log4Net&quot;, &quot;Warn&quot;);
            stringAppender.ToString().Should()
                .Be(&quot;WARN - &quot; + expected);
        }
    }
}
</pre>
</pre>
</div>
<p>Certo?!</p>
<p>Por agora, era isso. Em posts futuros, mostro mais detalhes sobre como escrever log de forma eficiente.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/learning-tests/'>Learning Tests</a>, <a href='http://elemarjr.net/tag/log4net/'>log4net</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2776/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2776/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2776/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2776&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/14/primeiros-passos-com-apache-log4net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb26.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://elemarjr.files.wordpress.com/2012/05/image_thumb27.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Qual &#233; o seu est&#225;gio de desenvolvimento moral?</title>
		<link>http://elemarjr.net/2012/05/13/qual-o-seu-estgio-de-desenvolvimento-moral/</link>
		<comments>http://elemarjr.net/2012/05/13/qual-o-seu-estgio-de-desenvolvimento-moral/#comments</comments>
		<pubDate>Sun, 13 May 2012 17:31:06 +0000</pubDate>
		<dc:creator>elemarjr</dc:creator>
				<category><![CDATA[Post]]></category>
		<category><![CDATA[carreira]]></category>
		<category><![CDATA[filosofando]]></category>

		<guid isPermaLink="false">https://elemarjr.wordpress.com/?p=2768</guid>
		<description><![CDATA[O Olá pessoal. Tudo certo?! Nessa útltima semana, tive a oportunidade de conhecer, através dos meus amigos @renatolorandi e @jjrigotti, o excelente trabalho de Lawrence Kohlberg. O centro do trabalho dele está no reconhecimento de que pessoas têm estágios de desenvolvimento moral diferentes. Logo, em função disso, reagem de forma diferente frente as questões do [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2768&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>O Olá pessoal. Tudo certo?!</p>
<p>Nessa útltima semana, tive a oportunidade de conhecer, através dos meus amigos <a href="twitter.com/renatolorandi">@renatolorandi</a> e <a href="https://twitter.com/#!/jjrigotti">@jjrigotti</a>, o excelente trabalho de <a href="http://pt.wikipedia.org/wiki/Lawrence_Kohlberg">Lawrence Kohlberg</a>.</p>
<p>O centro do trabalho dele está no reconhecimento de que pessoas têm estágios de desenvolvimento moral diferentes. Logo, em função disso, reagem de forma diferente frente as questões do dia-a-dia.</p>
<p>Esse post fala desse trabalho.</p>
<h2>A constatação de Lawrence Kohlberg</h2>
<p>Lawrence Kohlberg constatou que há seis estágios de desenvolvimento moral, divididos em três grupos:</p>
<ol>
<li><strong>Pré-moral, ou pré-convencional</strong>
<ul>
<li>Estágio 1 &#8211; Castigo e obediência</li>
<li>Estágio 2 &#8211; Troca Instrumental</li>
</ul>
</li>
<li><strong>Convencional</strong>
<ul>
<li>Estágio 3 &#8211; Conformidade interpessoal</li>
<li>Estágio 4 &#8211; Lei e ordem</li>
</ul>
</li>
<li><strong>Pós-convencional, ou baseado em princípios</strong>
<ul>
<li>Estágio 5 &#8211; Direitos básicos e contrato social</li>
<li>Estágio 6 &#8211; Ética e princípos universais.</li>
</ul>
</li>
</ol>
<p>Ainda segundo o trabalho dele, todos passamos, naturalmente, por esses estágios. Ou seja, ninguém nasce no estágio 3, por exemplo. Todos nascemos com nosso desenvolvimento moral baseado em Castigo e Obediência.</p>
<p>Não há relação entre idade e desenvolvimento moral. Pessoas morrem sem chegar perto do Estágio 6.</p>
<h2>Os estágios do desenvolvimento moral</h2>
<p>Para entender melhor o que cada um desses estágios significa, vamos analisar cada um deles isoladamente.</p>
<h3>Estágio 1 – Castigo e obediência</h3>
<p>Quem está nesse estágio tem seu sistema de valores e auto-percepção onde as atittudes estão relacionados ao fato de haver, ou não, castigo.</p>
<p>Estando nesse estágio de desenvolvimento, não avançamos o sinal vervelho por termos medo de sermos flagrados por um policial. Entretanto, quando tivermos certeza de que não seremos punidos, avançamos.</p>
<p>Crianças costumam ter esse perfil. Por isso, inicialmente, precisam receber exatamente esse direcionamento.</p>
<p>Infelizmente, muitos adultos AINDA estão nesse estágio. Quantas pessoas conhecemos que, quando têm certeza da impunidade, agem de forma desonesta.</p>
<p>Pessoas nesse estágio de desenvolvimento moral precisam de comando e controle (provocando o <a href="http://twitter.com/giovannibassi">@giovannibassi</a>).</p>
<p>Esse estágio deveria ser superado ainda na infância, mas, quantos adultos conhecemos com padrões de comportamento que destacam essa linha de pensamento moral.</p>
<h3>Estágio 2 – Troca Instrumental</h3>
<p>Quem está nesse estágio persegue seus próprios objetivos e interesses deixando os outros fazerem o mesmo.</p>
<p>Nesse estágio, há “uma-mão-lava-a-outra”, o “jeitinho”, a lei de Jerson.</p>
<p>Infelizmente, esse estágio está associado diretamente a classe política, no Brasil. Percebendo que essa “classe” é apenas uma amostra da população, então, estatisticamente, podemos dizer que esse é o nível de desenvolvimento moral da sociedade brasileira.</p>
<p>O mais impressionante é que este estágio é “superior” ao anterior.</p>
<p>Repare, nesse estágio, toleramos as “infrações” dos outros por entender que eles também podem/devem tolerar as nossas.</p>
<h3>Estágio 3 – Conformidade interpessoal</h3>
<p>Nesse estágio, valorizamos, confiamos, cuidamos e somos leais a quem pertence ao nosso grupo. Este estágio de desenvolvimento moral implica na existência de um “nós” e “eles”. Onde, nós estamos certos, eles estão errados; Nós somos bons, eles são maus; Nós somos competentes …</p>
<p>O importante, aqui, é ser aceito. Quem está nesse estágio acata as opiniões do “partido”, da “panelinha”, do “grupo de discussão”, da “igreja” e condena qualquer coisa que venha de fora.</p>
<h3>Estágio 4 – Lei e ordem</h3>
<p>Nesse estágio, os julgamentos são baseados na ordem social, nas leis, na justiça e no dever. Quem está nesse estágio realmente acredita que a lei, a ordem social, a justiça e outros valores são reais, são partes do gênero humano.</p>
<p>Nesse estágio, na medida que evoluímos, entendemos que valores, direitos e princípios formam a base das leis e as transcendem. Entendemos que há algo maior que o grupo.</p>
<h3>Estágio 5 – Direitos básicos e contrato social</h3>
<p>Nesse estágio, entendemos qu valores são universais, que os conceitos de certo e errado não foram definidos para controlar a sociedade. Mas, são inatos.</p>
<p>Nesse estágio, procuramos o bem do todo e, por isso, questionamos as leis que não estão de acordo com esses direitos. São os loucos que “questionam o sistema”, pelo aperfeiçoamento do sistema em favor do bem comum.</p>
<h3>Estágio 6 – Ética e princípios universais</h3>
<p>Nesse estágio, indivíduo age movido por princípios universais baseados na igualdade e no valor da vida humana.</p>
<p>Pessoas nesse estágio buscam o bem comum. Ou seja, o melhor para todos.</p>
<h2>Princípios do desenvolvimento moral</h2>
<p>Ainda de acordo com Lawrence Kohlberg, o desenvolvimento moral obedece a determinados princípios. Veja:</p>
<ul>
<li><strong>O desenvolvimento por estágios é invariável. </strong>Ou seja, não se pode &#8220;pular” estágios. Não podemos sair do “Castigo e Obidiência” para “Lei e Ordem” diretamente.</li>
<li><strong>Não podemos compreender o raciocínio moral que ocorre além do próximo estágio daquele em que estamos</strong>. Pessoas em estágios diferentes, ao discutir ética, tem interpretações muito diferentes.</li>
<li><strong>Os indivíduos são cognitivamente atraídos por raciocínios um estágio acima do nível em que se encontram. </strong></li>
<li><strong>A evolução de um estágio para outro se verifica quando é criado um desequilíbrio cognitivo ou emocional. </strong>Isso ocorre quando nossa interpretação da vida já não é adequada para a solução de um determinado dilema moral.</li>
</ul>
<h2>O politicamente correto</h2>
<p>Estamos em tempos do “politicamente correto”. Para mim, trata-se de uma encenação de “Ética e princípios universais” por parte de indivíduos que, na maioria dos casos, ainda vive “Troca Instrumental”. Consequência: estamos condenando o “falar errado”, mas estamos fazendo pouco a respeito do “fazer errado”.</p>
<h2>O estágio de desenvolvimento moral e a ética</h2>
<p>Ética é um conjunto de valores. Quando dizemos que uma pessoa, ou empresa, é ética, nos referimos a seus valores.</p>
<p>Se meus valores E MINHAS ATITUDES estão de acordo com determinado estágio de desenvolvimento moral, então, isso é ética.</p>
<p>Valores são observados a partir do estágio 4. Logo, antes disso, não podemos identificar como ética qualquer pessoa (ou empresa formada por pessoas) que estejam em estágios mais baixos.</p>
<h2>Para pensar …</h2>
<p>Identificar o estágio em que nos encontramos é uma excelente oportunidade para que possamos observar as características que norteiam o próximo estágio. É uma oportunidade de promover o tal “desequilíbrio cognitivo”.</p>
<p>Reconhecer o estágio de desenvolvimento moral nos outros é uma excelente oportunidade de encontrarmos referências para o nosso desenvolvimento. Ou ainda, perceber como “falar a língua” do outro – promovendo, no outro, o “desequilíbrio cognitivo” que ele precisa para evoluir.</p>
<p>O desequilíbrio cognitivo se dá pelo “questionamento moral”.</p>
<p>Afinal, qual é o seu estágio de amadurecimento moral?!</p>
<p>Era isso.</p>
<br /> Tagged: <a href='http://elemarjr.net/tag/carreira/'>carreira</a>, <a href='http://elemarjr.net/tag/filosofando/'>filosofando</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/elemarjr.wordpress.com/2768/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/elemarjr.wordpress.com/2768/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/elemarjr.wordpress.com/2768/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=elemarjr.net&#038;blog=14656382&#038;post=2768&#038;subd=elemarjr&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://elemarjr.net/2012/05/13/qual-o-seu-estgio-de-desenvolvimento-moral/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/784c5d06fca162d5fc3fbe59e25e5180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">elemarjr</media:title>
		</media:content>
	</item>
	</channel>
</rss>
