Série Redis on Azure – Criando nossa base Redis e desenvolvendo nosso primeiro Cache

Seguindo a nossa série sobre a utilização do Redis no Azure, nesse artigo vamos criar nossa base Redis e vamos desenvolver um exemplo. Caso tenha perdido o artigo anterior, ele pode ser acessado através deste link.

Vale lembrar que, caso ainda não tenha uma subscription no Azure, será necessário criar uma (caso queira um passo a passo, clique aqui).

Criando nosso Redis no Azure

Primeiro vamos acessar o Portal do Azure através do link: https://portal.azure.com e efetuar o nosso login. Já no portal do Azure, vamos clicar em “Create a Resource>Databases>Redis Cache“, conforme na figura abaixo:

Redis on Azure
Figura 1

Feito isso, vamos preencher os dados e depois clicar em “Create” para a criação do nosso serviço de cache, conforme nos mostra a figura 2 abaixo:

Redis on Azure
Figura 2

O processo para finalizar a criação do serviço leva em média 15 minutos, e assim que ele terminar, acesse o Redis e clique em “Keys“. Em seguida, copie o endereço da Primary connection string, conforme nos mostra a figura abaixo:

Redis on Azure
Figura 3

Agora vamos esquecer por um breve momento o Azure e vamos criar uma aplicação do tipo Web API utilizando o ASP.NET Core 2. Se estiver usando o Visual Studio Code, é só abrir o terminal, navegar até a pasta desejada e digitar o comando:

dotnet new webapi

Após o termino da criação do projeto, abra o arquivo appsettings.json e crie uma conexão com a string de conexão do Redis que copiamos anteriormente, conforme o código abaixo:

"ConnectionStrings": {
    "RedisConn": "conexão do seu redis"
}

Agora no nosso arquivo Startup.cs, vamos adicionar o seguinte código:

services.AddDistributedRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("RedisConn");
    options.InstanceName = "ericsonfInstance";
});

E por último, vamos criar um Controller chamado RedisCacheController e dentro dele no método Get, vamos criar nosso cache através da Interface IDistributedCache, utilizando o código abaixo (comentários no próprio código para melhor entendimento):

public class RedisCacheController : Controller
{
    private readonly IDistributedCache _distributedCache;

    public RedisCacheController(IDistributedCache distributedCache)
    {
        _distributedCache = distributedCache;
    }

    // GET api/RedisCache
    [HttpGet]
    public string Get()
    {
        //Variável que vai receber uma data
        var date = string.Empty;
        //Key utilizada para armazenarmos o nosso cache (que será a data)
        var key = "distributedCacheKey";

        //Verifico se o cahce já existe
        date = _distributedCache.GetString(key);
        //Se existir exibo o texto Data cache com a data cacheada.
        if (!string.IsNullOrEmpty(date))
        {
            return string.Concat("Data cache: ", date);
        }
        //Senão criamos nosso cache com a data atual
        else
        {
            date = DateTime.Now.ToString();
            /* Nesta linha diz que o cache permanecera ativo para sempre desde que num periodo de 10 segundos alguém acesse ele.
            Caso você deseje que o cache desapareça em um determinado periodo de tempo independentemente de acesso,
            troque o comando SetSlidingExpiration para SetAbsoluteExpiration. */
            var cacheExpiration = new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(10));
            //Cache sendo criado
            _distributedCache.SetString(key, date, cacheExpiration);
            //Retorno a Data atual pois ainda não havia nenhum cache com a key distributedCacheKey
            return string.Concat("Data atual: ", date);
        }
    }
}

Agora execute o projeto e veja que inicialmente ele trouxe a Data atual. Se você atualizar seu browser, verá que ele mudará o texto para Data cache sem alterar a data em si.

Para você visualizar o cache em si salvo no Redis, volte novamente para o Portal do Azure e clique em >_ Console, para abrir o console do Redis e nele digite monitor. Feito isso, execute novamente a aplicação e observe a sua Key e a data cacheada conforme mostram as figuras abaixo:

Redis on Azure
Figura 4
Redis on Azure
Figura 5

Como você pode observar, o mesmo data cacheado na tela é o mesmo que está salvo no Redis.

No próximo artigo da série utilizaremos outras maneiras de criar nosso cache e de administra-lo. E assim termino mais um artigo, espero que tenham gostado e até o próximo.

Série Redis on Azure – O que é Redis e para que serve

Neste artigo pretendo iniciar uma série de artigos que vão focar em como utilizar o Redis no Azure através de exemplos práticos para os mais diversos cenários. E para iniciar essa série, vamos primeiramente entender o que é o Redis e para que ele serve de fato.

Redis

O Redis (REmote DIctionary Server) é uma estrutura de armazenamento em memória, NoSQL de chave-valor e open source. Apesar de possuir diversas utilidades (discutiremos elas mais adiante) o Redis é costumeiramente utilizado para armazenamento de cache visando sempre melhorar o desempenho de sistemas que dependem de uma grande quantidade de dados vindos do back-end.

Pelo fato do seu armazenamento ser feito em memória, ele é extremamente rápido, chegando a performance de 110.000 SETs e 81.000 GETs por segundo.

Outros dois pontos importantíssimos, são:

  • Suas operações são atômicas, ou seja, uma operação sempre retornará sucesso ou falha obrigatoriamente.
  • O Redis é single-threaded, e nesse caso, um fator que vale a pena mencionar é que um processador rápido com bastante cache se sobressai, se comparado com um processador de muitos núcleos com pouco cache.

Apesar de ser uma estrutura chave-valor, o Redis possui um conjunto bem rico de tipos de dados, sendo os principais:

  • Strings: tipo mais básico do Redis. Eles são binários, e com isso, o tipo String pode conter qualquer tipo de dado como, por exemplo, uma imagem. Vale pontuar que o tamanho máximo da String é 512 mb.
  • Lists: esse tipo nada mais é do que uma lista de Strings, classificadas por ordem de inserção. O Redis suporta uma lista de strings contendo até aproximadamente 4 bilhões de elementos.
  • Sets: é uma colação não ordenada de Strings. Por padrão, os Sets não permitem elementos repetidos, sendo que adicionando o mesmo elemento várias vezes resultará em um outro conjunto com uma cópia unica desse elemento. Assim como as Lists, os Sets também podem armazenar aproximadamente 4 bilhões de elementos.
  • Sorted Sets: semelhante aos Sets, porém com o recurso de serem ordenados, cada elemento é associado a um Score, sendo que a ordenação é feita sobre ele.
  • Hash: utilizado majoritariamente para representar um objeto, sendo que ele mapeia um atributo e seu respectivo valor (assim como em um objeto).

A respeito de sua aplicabilidade, conforme mencionado no inicio do artigo, o Redis é bastante versátil, se saindo bem nos mais variados cenários, sendo os principais:

  • Armazenamento em cache (cache de conteúdo): nesse cenário o Redis serve para armazenar conteúdos que raramente são alterados, trazendo maior velocidade e consequentemente melhorando o desempenho das aplicações. Com isso, podemos poupar por requisições desnecessárias no servidor.
  • Gerenciamento de Sessão (cache de sessão): aqui, o Redis pode armazenar sessões com um tempo de vida já definido, sendo perfeito para armazenar informações de um usuário logado na sua aplicação, bem como um carrinho de compras e etc.
  • Classificações em Real-Time (cache-aside): usando o sorted set, você pode criar um rank e atualizá-lo conforme demanda (cache-aside) garantindo que sua aplicação mostre uma classificação em tempo real.
  • Filas: Sendo single-threaded e suas operações atômicas, o Redis é uma ótima opção para ser usado como um agente de mensagens.

Agora que temos uma boa base sobre como Redis funciona e seus principais cenários de aplicação, no nosso próximo artigo vamos por a mão na massa e criar nosso servidor no Azure e então, começar a implementar alguns exemplos abordados nesse primeiro artigo.

Espero que tenham gostado e até o próximo artigo!

Obrigado.

Introdução a Clean Architecture

Criada em meados de 2012 por Robert Cecil Martin (“Uncle Bob”), a Clean Architecture tem como principais finalidades ser independente de frameworks, facilmente testável, independentemente da interface do usuário, ou seja, a interface do usuário pode mudar à vontade sem que isso reflita no resto do sistema, ser independente de banco de dados, já que ela mantém todas as regras de negócio na própria aplicação e, por último, ser independente de qualquer agente externo, sendo que as regras de negócio não “enxergam” o “mundo exterior”. Resumindo, a Clean Architecture é um tipo de arquitetura de software amplamente independente.

Neste artigo, mostraremos o conceito dessa arquitetura e também um exemplo de como implementá-la no mundo real.

Clean Architecture

Clean Architecture
Fonte: https://bit.ly/2a1px8t

Dependências

Na imagem acima, temos o desenho de como a Clean Architecture funciona. Note que as setas horizontais da imagem que representam as dependências entre as camadas vêm de “fora para dentro”, ou seja, a camada Framework “enxerga” somente a Interface Adapters, que por sua vez “enxerga” somente a User Cases, que finalmente “enxerga” apenas a Entites. Esta é a principal regra da Clean Architecture, e talvez sua única: o Princípio da Dependência.

As camadas internas não devem ter qualquer dependência das externas, nem indiretas, como nomes de variáveis, funções ou termos.

Provavelmente você terá mais abstrações nas camadas internas e mais implementações nas externas, utilizando injeção de dependência para fazer tudo funcionar.

Entities

Camada que encapsula as entidades e regras de negócio. O principal entendimento aqui é que essa camada deve conter tudo que seja pertinente ao sistema como um todo de uma maneira mais genérica, ou seja, deve conter as regras que tenham menos possiblidades de mudança quando algo externo mudar, como algo na interface do usuário.

Em um grande sistema, que reusa código da empresa, aqui poderiam residir as bibliotecas que são consumidas pela aplicação, mas que a aplicação não irá modificar, como algum framework ou outros domínios de negócio. Em uma aplicação menor, podem ser apenas interfaces e classes que tenham que ser utilizadas em todas as camadas, como a interface de um repositório.

User cases

Essa camada é a que contém as regras de negócios mais específicas do sistema. É aqui que todos os casos de uso do sistema são implementados. É esperado que apenas mudanças de requisitos afetem essa camada, sendo que assim como na Entities, alterações nas camadas externas não devem afetar essa camada. (sugestão: essa camada. No entanto, assim como na Entities, alterações…)

Interface Adapters

Camada que tem como finalidade converter dados da maneira mais acessível e conveniente possível para as camadas Entities e User Cases. Um exemplo seria o uso do AutoMapper, onde eu poderia controlar as estruturas transmitidas entre User Cases e Entities com o interface do usuário, por exemplo.

Frameworks

Essa camada é composta por ferramentas como banco de dados, interface do usuário etc. Nessa camada, a ideia ée ter o mínimo de código possível, apenas o necessário para interligar as camadas e injetar as implementações necessárias nas camadas interiores.

Usando a Clean Architecture no mundo real

Para facilitarmos o entendimento, criamos um exemplo bem simples de um sistema escolar, no qual vamos cadastrar novas turmas. A estrutura base do projeto foi divida nas camadas: Core, Entities, UseCases e Web, conforme nos mostra a imagem abaixo:

Clean Architecture Example

A camada Core foi incluída a fim de ter um nível de abstração ainda maior do que a Entities. Essa camada possui apenas um repositório padrão (IRepository), um interactor que vai receber uma entrada e nos devolver uma resposta (IInteraction) e uma entidade que possui as propriedades que serão utilizadas por todas as classes (IEntity). Outra coisa interessante nessa camada é que ela contém todos os pacotes que serão utilizados pelas outras camadas, já que, conforme dito anteriormente, as dependências são de “fora para dentro”.

Na camada Entities, temos as Classes que de fato compõem o sistema – observe que ela conhece a camada Core, uma vez que ela é menos abstrata.

Na camada UseCases, possuímos todas as nossas regras de negócio. Observe que temos apenas três arquivos para a entidade Turma, sendo um arquivo de Input que vai receber os dados (CadastrarTurmaInput), um Interactor (CadastrarTurmaInteractor) que contém todas as regras de negócio implementadas – por exemplo, ao cadastrar uma Turma será que existe um professor disponível? Ou será que já não existe uma turma para mesma data? – e por último um arquivo de output (CadastrarTurmaOutput) que vai transformar os dados para que possa ser exibido. (possam ser exibidos? Fiquei em dúvida se isso se refere a dados)

Nossa última camada, a Web, vai apenas consumir os dados transformados pela camada anterior e exibi-los para o usuário. Ela também é responsável, nesta implementação simplificada, por injetar os repositórios para consumo nos interactors, e os interactors para consumo pelos controllers.

Conforme vimos no exemplo do sistema escolar, cada camada possui uma única responsabilidade sempre respeitando suas dependências, mantendo assim uma divisão total de responsabilidades, minimizando ao máximo qualquer alteração externa com interface com o usuário (de usuário?), banco de dados etc.

Caso queiram baixar o código utilizado no exemplo, ele pode ser encontrado através deste link.

Fonte: https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

***

Esse artigo foi publicado na revista iMasters, edição #27: https://issuu.com/imasters/docs/imasters_27_issuu

Convertendo consultas T-SQL em LINQ

Se você já teve e/ou tem bastante vivência com a linguagem T-SQL e hoje se depara com o um software que tenha um ORM para fazer as transações com o banco de dados, pode ser que aparecem algumas dúvidas sobre como “converter” uma querie T-SQL na “linguagem” que o ORM entende.

Se você se deparar com essa situação e tiver alguma dúvida quanto a alguma consulta que precisa converter, esse post é destinado a você.

Nesse post vamos utilizar o Entity Framework como ORM e a linguagem LINQ to Entities que permite aos desenvolvedores escreverem consultas nesse modelo usando VB ou C#.

Abaixo segue o modelo que utilizei para facilitar o entendimento das consultas.

Figura 1

SELECT COM UM TOP

T-SQL:  SELECT TOP 2 Nome FROM Artista;

LINQ:   var result = (from a in context.Artista select a.Nome).Take(2);

LAMBDA: var result = context.Artista.Select(a => a.Nome).Take(2);

SELECT COM UM WHERE

T-SQL:  SELECT Nome FROM Artista WHERE Nome = ‘Led Zeppelin’;

LINQ:   var result = (from a in context.Artista 
                    where a.Nome.Equals(“Led Zeppelin”) 
                    select a.Nome).ToList();

LAMBDA: var result = context.Artista
                    .Where(a => a.Nome.Equals(“Led Zeppelin”))
                    .Select(a => a.Nome).ToList();

SELECT COM UM INNER JOIN

T-SQL: 	SELECT a.Nome, al.Titulo FROM Artista a 
       	    INNER JOIN Album al ON al.ArtistaId = a.ArtistaId;

LINQ:   var result = (from a in context.Artista
            join al in context.Album on a.ArtistaId equals al.ArtistaId
            select new
            {
                a.Nome,
                al.Titulo
            }).ToList();

LAMBDA: var result = context.Artista
            .Join(context.Album, artista => artista.ArtistaId, album => album.ArtistaId,
            (artista, album) => new { Artista = artista, Album = album })
            .Select(a => new { 
                Nome = a.Artista.Nome, 
                Titulo = a.Album.Titulo 
            }).ToList();

SELECT COM DUAS CONDIÇÕES NO MESMO INNER JOIN

T-SQL:  SELECT DISTINCT a.Nome, al.Titulo FROM Artista a 
            INNER JOIN Album al ON al.ArtistaId = a.ArtistaId AND al.Titulo = a.Nome;

LINQ:   var result = (from a in context.Artista
            join al in context.Album on
            new { C1 = a.ArtistaId, C2 = a.Nome } equals 
            new { C1 = al.ArtistaId, C2 = al.Titulo }
            select new
            {
                a.Nome,
                al.Titulo
            }).ToList();

LAMBDA: var result = context.Artista
        .Join(context.Album, artista => new { C1 = artista.ArtistaId, C2 = artista.Nome }, 
            album => new { C1 = album.ArtistaId, C2 = album.Titulo },
            (artista, album) => new { Artista = artista, Album = album })
        .Select(a => new { 
            Nome = a.Artista.Nome, 
            Titulo = a.Album.Titulo 
        }).ToList();

SELECT COM DOIS INNER JOINS

T-SQL:  SELECT a.Nome, al.Titulo, f.Nome FROM Artista a
            INNER JOIN Album al ON al.ArtistaId = a.ArtistaId
            INNER JOIN Faixa f ON f.AlbumId = al.AlbumId;

LINQ:   var result = (from a in context.Artista
        join al in context.Album on a.ArtistaId equals al.ArtistaId
        join f in context.Faixa on al.AlbumId equals f.AlbumId
        select new
        {
            Artista = a.Nome,
            Album = al.Titulo,
            Faixa = f.Nome
         }).ToList();

LAMBDA: var result = context.Artista
        .Join(context.Album, artista => artista.ArtistaId, album => album.ArtistaId,
            (artista, album) => new { Artista = artista, Album = album })
        .Join(context.Faixa, album => album.Album.AlbumId, faixa => faixa.AlbumId,
            (album, faixa) => new { Album = album, Faixa = faixa })
        .Select(a => new { 
            Nome = a.Album.Artista.Nome, 
            Titulo = a.Album.Album.Titulo, 
            Faixa = a.Faixa.Nome 
        }).ToList();

SELECT COM UM LEFT JOIN

T-SQL:  SELECT a.Nome, al.Titulo FROM Artista a
            LEFT JOIN Album al ON al.ArtistaId = a.ArtistaId;

LINQ:   var result = (from a in context.Artista
            join al in context.Album on a.ArtistaId equals al.ArtistaId 
                into All from al in All.DefaultIfEmpty()
            select new
            {
                a.Nome,
                al.Titulo
            }).ToList();

LAMBDA: var result = context.Artista
            .GroupJoin(context.Album, artista => artista.ArtistaId, album => album.ArtistaId,
                (artista, album) => new { Artista = artista, Album = album.DefaultIfEmpty() })
            .SelectMany(a => a.Album, (a, album) => new { 
                a.Artista.Nome, 
                album.Titulo 
            }).ToList();

SELECT COM DOIS LEFT JOINS, GROUP BY e COUNT

T-SQL:  SELECT DISTINCT a.Nome, (SELECT COUNT(*) AS Album FROM Album WHERE ArtistaId = a.ArtistaId) AS Album, 
            	COUNT(f.FaixaId) AS Faixa 
        	FROM Artista a
            LEFT JOIN Album al ON al.ArtistaId = a.ArtistaId
            LEFT JOIN Faixa f ON f.AlbumId = al.AlbumId
            GROUP BY a.Nome, a.ArtistaId;

LINQ:   var result = (from a in context.Artista
        join al in context.Album on a.ArtistaId equals al.ArtistaId 
            into All1 from al in All1.DefaultIfEmpty()
        join f in context.Faixa on al.AlbumId equals f.AlbumId 
            into All2
        from f in All2.DefaultIfEmpty()
        group a by a into grouped
        let totalAlbuns = grouped.Key.Album.Count()
        let totalFaixas = grouped.Count(x => x.Album.Count > 0)
        select new
        {
            Artista = grouped.Key.Nome,
            Albuns = totalAlbuns,
            Faixas = totalFaixas
        }).ToList();

LAMBDA: var result = context.Artista
            .GroupJoin(context.Album, artista => artista.ArtistaId, album => album.ArtistaId,
                (artista, album) => album.Select(x => new { 
                                                    Artista = artista, 
                                                    Album = x 
                                                })
            .DefaultIfEmpty(new { 
                Artista = artista, 
                Album = (Albuns)null 
            }))
            .SelectMany(x => x)
            .GroupJoin(context.Faixa, 
                album => album.Album.AlbumId, 
                faixa => faixa.Album.AlbumId,
               	    (album, faixa) => faixa.Select(y => new { 
                                                Artista = album.Artista, 
                                                Album = album.Album, 
                                                Faixa = y 
                                            })
            .DefaultIfEmpty(new { 
                Artista = album.Artista, 
                Album = album.Album, 
                Faixa = (Faixas)null 
            }))
            .SelectMany(y => y)
            .GroupBy(grouped => new { grouped.Artista })
            .Select(g => new
            {
                Artista = g.Key.Artista.Nome,
                Albuns = g.Key.Artista.Album.Count(),
                Faixas = g.Count(x => x.Album.Faixa.Count > 0)
            }).ToList();

Como vocês puderam ver a ideia desse artigo foi de ser o mais direto ao ponto possível. Obviamente, é impossivel cobrir todos os cenários possíveis de se fazer consultas T-SQL, então tentei  colocar desde um exemplo simples até um exemplo um pouco mais complexo.

Espero que tenham gostado e até a próxima.

Serialização em C#

Antes de irmos diretamente para o código, vamos entender brevemente o que é serialização e deserialização. 

Serializar é o processo de transformar um objeto que você possui em um stream de bytes ou de texto. Deserializar por sua vez, é exatamente o oposto, é você converter um stream de bytes ou de texto em um objeto novamente. 

Para nos ajudar nesse processo, o .NET Framework nos oferece algumas classes que podem ser encontradas nos namespaces System.Runtime.Serialization e System.Xml.Serialization, além de nos oferecer por padrão três mecanismos serialização/deserialização: 

public class Person 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Email { get; set; } 
    public int Age; 

    public Person() { } 

    public Person(int id, string firstName, string lastName, string email, int age) 
    { 
        Id = id; 
        FirstName = firstName; 
        LastName = lastName; 
        Email = email; 
        Age = age; 
    } 
}
  • BinaryFormatter 
  • XmlSerializer 
  • DataContractSerializer 

Logo mais nesse artigo veremos como utilizar cada um desses mecanismos na prática, portanto usaremos a classe Person, que se encontra logo abaixo como base para nossos exemplos. 

Binary Serialization 

A serailização Binária, como o próprio nome já sugere, serializa um objeto ou dado para o formato binário. Esse tipo de serialização armazena não somente os dados, mas também o tipo de objeto que esta sendo serializado. 

Para utilizarmos esse tipo de serialização, devemos marcar nossa classe como o atributo [Serializable], sendo que todos os campos podem ser serializados, inclusive os marcados como private, portanto caso queiramos impedir que algum campo da nossa classe não seja serializado, devemos marca-la com o atributo [NonSerialized], também é importante ressaltarmos que propriedades serão sempre serializadas e que nenhum construtor é executado nesse tipo de serialização. 

Outra característica importante é que esse tipo de serialização também é “mais rigorosa” que as demais, se o serializador binário não achar algum campo por exemplo, ele retornará uma Exception. No caso de uma atualização de versão por exemplo, você pode adicionar o [OptionalFieldAttribute] no novo campo adicionado para que a serialização binária entenda que esse campo não existia antes, por exemplo. 

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe BinarryFormatter 
var binaryFormatter = new BinaryFormatter(); 

//Criamos um arquivo .bin que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("ericsonf.bin", FileMode.Create)) 
{ 
    binaryFormatter.Serialize(fileStream, person); 
} 

Console.WriteLine("Serialização Concluida"); 
 
//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("ericsonf.bin", FileMode.Open)) 
{ 
    var p = (Person)binaryFormatter.Deserialize(fileStream); 
} 

Console.WriteLine("Deserialização Concluida");

XML Serialization 

Ao contrário do modelo de serialização anterior, o XML é um tipo de dado legivel também para seres humanos, e é fracamente acoplado, ou seja, se você adicionar propriedades ou campos ao seu objeto a ser serializado ele não notará. 

Assim como na serialização binária, para serializamos, precisamos marcar o objeto como o atributo [Serializable], entretanto, aqui somente os campos e/ou propriedades publicas são serializadas. Caso queiramos que um campo e/ou propriedade não seja serializado, devemos marca-lo com o atributo [XmlIgnore]. Vale lembrar que propriedades também podem ser ignoradas e não somente campos, além de que, na serialização XML se faz necessário ter um construtor vazio na classe diferentemente do modelo de serialização anterior. 

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe XmlSerializer, e "dizemos" a ele que tipo de objeto vamos serializar. 
var xml = new XmlSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("ericsonf.xml", FileMode.Create)) 
{ 
    xml.Serialize(fileStream, person); 
} 

Console.WriteLine("Serialização Concluida"); 

//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("ericsonf.xml", FileMode.Open)) 
{ 
    var p = (Person)xml.Deserialize(fileStream); 
} 

Console.WriteLine("Deserialização Concluida"); 

Data Contract 

O Data Contract Serializer é utilizado pelo WCF para serializar seus objetos tanto em XML quanto em JSON. Esse tipo de serialização é feita pelas classes DataContractSerializer para XML e DataContractJsonSerializer para JSON (discutido mais adiante).  

Nesse modelo eu preciso marcar meu objeto a ser serializado com o atributo [DataContract], além de que nesse modelo ao contrario dos outros, eu preciso marcar todos os membros que eu desejo serializar explicitamente com o atributo [DataMember], caso eu deseje ignorar algum membro, devemos marca-lo com o atributo [IgnoreDataMember] ou se preferir, apenas deixa-lo sem a marcação do atributo [DataMember]. Outra caracteristica importante é que nesse modelo, campos privados também pode ser serializados. 

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe DataContractSerializer, para serializarmos em XML e "dizemos" a ele que tipo de objeto vamos serializar. 
var dataContract = new DataContractSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("ericsonf.xml", FileMode.Create)) 
{ 
    dataContract.WriteObject(fileStream, person); 
} 

Console.WriteLine("Serialização Concluida"); 

//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("ericsonf.xml", FileMode.Open)) 
{ 
    var p = (Person)dataContract.ReadObject(fileStream); 
} 

Console.WriteLine("Deserialização Concluida");

JSON Serialization 

Utiliza-se também o  Data Contract Serializer e suas respectivas caracteristicas para que a serilização seja efetuada, porém com uma única alteração, que ao invés de eu utilizar a classe DataContractSerializer eu utilizo a classe DataContractJsonSerializer para que possamos serializar em JSON. 

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe DataContractJsonSerializer, para serializarmos em JSON e "dizemos" a ele que tipo de objeto vamos serializar. 
var dataContract = new DataContractJsonSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("ericsonf.json", FileMode.Create)) 
{ 
    dataContract.WriteObject(fileStream, person); 
} 

Console.WriteLine("Serialização Concluida"); 

//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("ericsonf.json", FileMode.Open)) 
{ 
    var p = (Person)dataContract.ReadObject(fileStream); 
} 

Console.WriteLine("Deserialização Concluida");

Bom pessoal, a ideia desse artigo era mostrar a vocês as particularidades e exemplos de como utilizar cada dos modelos de serialização utilizando C#. 

Espero que tenham gostado do artigo e até a próximo.