Mediator Pattern com MediatR no ASP.NET Core \| TreinaWeb               Promoção no ar   Matricule-se agora e garanta **54% de desconto**  

  Termina em   Tempo restante da oferta: 14 Horas 

 52 Min 

 07 Seg 

   Tempo restante da oferta: 14 52 07 

  [Assinar →](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26) 

   [                ](https://www.treinaweb.com.br)  Explorar  

 [ Quanto custa? ](#assinatura) [ FAQ ](https://www.treinaweb.com.br#faq) [Matricule-se](#assinatura) [ Entrar ](https://www.treinaweb.com.br/login) 

     [ Início ](https://www.treinaweb.com.br) [ Artigos ](https://www.treinaweb.com.br/blog) Mediator Pattern com MediatR no ASP.NET Core  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) [ ASP .NET ](https://www.treinaweb.com.br/blog/categoria/asp-net) [ Padrões de Projeto ](https://www.treinaweb.com.br/blog/categoria/padroes-de-projeto) [ .NET Core ](https://www.treinaweb.com.br/blog/categoria/net-core) 

# Mediator Pattern com MediatR no ASP.NET Core

 Manter os objetos isolados é o objetivo do Mediator Pattern. No ASP.NET Core a sua implementação é facilitada com a biblioteca MediatR.

 [ Wladimilson M. Nascimento ](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento) 7 anos atrás

  ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/05/05142558/mediator-pattern-com-mediatr-no-asp-net-core.png)  

Para facilitar o desenvolvimento, a manutenção e [manter o código limpo e legível](https://www.treinaweb.com.br/blog/dicas-para-manter-seu-codigo-limpo-e-legivel), grandes aplicações procuram seguir [princípios SOLID](https://www.treinaweb.com.br/blog/introducao-aos-principios-solid/), [padrões de projetos](https://www.treinaweb.com.br/blog/padroes-de-projeto-o-que-sao-e-o-que-resolvem/) e outras recomendações de boas práticas, como a desacoplação dos objetos. Neste grupo de recomendações, vem ganhando espaço a adoção do Mediator Pattern, que no ASP.NET pode ser facilmente implementado com a biblioteca MediatR, como veremos neste artigo.

[  ![C# - Algoritmos](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/c-sharp.svg)   Curso C# - Algoritmos Conhecer o curso ](https://www.treinaweb.com.br/curso/c-sharp-algoritmos)

## O que é Mediator Pattern?

Mediator é um padrão de projetos comportamental especificado pela GoF, que na sua definição formal é descrito como:

> Um objeto que encapsula a forma como um conjunto de objetos interage. O Mediator promove o acoplamento fraco ao evitar que os objetos se refiram uns aos outros explicitamente e permite variar suas interações independentemente.

Em outras palavras podemos dizer que o Mediator Pattern gerencia as interações de diferentes objetos. Através de uma classe mediadora, centraliza todas as interações entre os objetos, visando diminuir o acoplamento e a dependência entre eles. Desta forma, neste padrão, os objetos não conversam diretamente entre eles, toda comunicação precisa passar pela classe mediadora.

Podemos ilustrar seu funcionamento com a imagem abaixo:

![Representação Gráfica do Mediator Pattern. Há setas apontando e saindo do objeto Mediator para representar a comunicação.](https://dkrn4sk0rn31v.cloudfront.net/2020/05/05151021/representacao-grafica-do-mediator-pattern.png)

Se um objeto, por exemplo, **Objeto A**, quiser se comunicar com outro, **Objeto C**, terá que passar pelo **Mediator**. Com isso, cada objeto pode focar apenas na sua responsabilidade e não precisa conhecer a estrutura do outro para realizar a comunicação. Se **Objeto C** for modificado, **Objeto A** não precisa tomar conhecimento disso, ou seja, cada objeto trabalha de forma independente e isolada.

Entretanto, se houver um grande fluxo de comunicação entre os objetos, o objeto mediador pode se tornar um gargalo para a aplicação. Para resolver isso, a solução comum é implementar o **CQRS** (**Command Query Responsibility Segregation**), em tradução livre, Segregação de Responsabilidade de Comando e Consulta.

## CQRS vem ao resgate

O [**Command Query Responsibility Segregation**](https://martinfowler.com/bliki/CQRS.html), ou **CQRS**, é um padrão de projeto que separa as operações de leitura e escrita da base de dados em dois modelos: *queries* e *commands*. Os *commands* são responsáveis pelas ações que realizam alguma alteração na base de dados. Geralmente operações assíncronas que não retornam nenhum dado.

Já as *queries* são responsáveis pelas consultas, retornando objetos DTOs (Data Transfer Object) para que seja isolada do domínio.

Por gerarem o maior fluxo de informações da aplicação, as consultas podem ser otimizadas através de um serviço específico, como um servidor de cache. Do lado dos *commands*, o Mediator pode ser utilizado para gerenciar a comunicação dos objetos.

É por causa disso que a biblioteca **MediatR** implementa conceitos do CQRS, porém não vou me aprofundar nele, já que não é objetivo desse artigo.

## O MediatR entra em cena

O [MediatR](https://github.com/jbogard/MediatR) é uma biblioteca open source criada por [Jimmy Bogard](https://github.com/jbogard), o mesmo criador da [biblioteca AutoMapper](https://www.treinaweb.com.br/blog/utilizando-automapper-no-c/). O seu objetivo é facilitar a implementação do Mediator Pattern em aplicações .NET. Com ela não precisamos nos preocupar com a criação da classe mediadora, pois já são fornecidas interfaces que facilitam a implementação do fluxo de comunicação entre os objetos.

## Colocando a mão na massa

Agora que conhecemos os conceitos por trás da biblioteca MediatR, vamos para um exemplo de implementação em um projeto. Será o projeto de uma [API](https://www.treinaweb.com.br/blog/o-que-e-uma-api/) simples com um CRUD de pessoas.

A primeira coisa a ser feita é a criação do projeto:

```dos
dotnet new webapi -n MediatRSample

```

Em seguida, iremos adicionar a biblioteca:

```dos
dotnet add package MediatR

```

Para uma aplicação ASP.NET Core, também é necessário instalar o pacote de [injeção de dependência](https://www.treinaweb.com.br/blog/entendendo-injecao-de-dependencia/):

```dos
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

```

Com o projeto criado e as dependências adicionadas, vamos adicionar algumas pastas nele, para que o nosso código fique mais organizado. O projeto ficará com a seguinte estrutura:

![Projeto ASP.NET Core, com uma pasta Application, que contém seis pastas: Commands, EventHandlers, Handlers, Models e Notifications.](https://dkrn4sk0rn31v.cloudfront.net/2020/05/05141802/estrutura-do-projeto-mediatrsample-com-seis-novas-pastas.png)

Onde dentro da pasta `Application`, temos as pastas:

- `Commands`: Onde serão definidos os objetos DTOs que representam uma ação a ser executada;
- `EventHandlers`: Onde serão definidos objetos responsáveis por receber uma notificação gerada pelos Handlers;
- `Handlers`: Onde serão definidos objetos responsáveis por receber as ações definidas pelos `Commands`;
- `Models`: Onde serão definidas as entidades utilizadas pela aplicação;
- `Notifications`: Onde serão definidos os objetos DTOs que representam notificações.

Vamos implementar as classes dessas pastas.

[  ![C# (C Sharp) - ASP.NET MVC](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp-avancado-asp-net.svg)   Curso C# (C Sharp) - ASP.NET MVC Conhecer o curso ](https://www.treinaweb.com.br/curso/csharp-avancado-asp-net-mvc)

## Especificando a classe domínio e o repositório da aplicação

Antes de implementar os objetos que farão uso da biblioteca MediatR, é necessário especificar a nossa classe de domínio, o model `Pessoa`:

```csharp
public class Pessoa
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public int Idade { get; set; }
    public char Sexo { get; set; }
}

```

Esta classe contém todas as propriedades que necessitamos para representar um objeto pessoa na nossa aplicação. Os *commands* que iremos definir serão baseados nela.

Por se tratar de um exemplo simples, esta aplicação não fará uso de um banco de dados, mas possuirá uma interface `IRepository`:

```csharp
public interface IRepository
{
    Task GetAll();

    Task Get(int id);

    Task Add(T item);

    Task Edit(T item);

    Task Delete(int id);
}

```

E uma classe repositório que salva os dados em uma coleção estática:

```csharp
public class PessoaRepository : IRepository
{
    private static Dictionary pessoas = new Dictionary();

    public async Task GetAll(){
        return await Task.Run(() => pessoas.Values.ToList());
    }

    public async Task Get(int id){
        return await Task.Run(() => pessoas.GetValueOrDefault(id));
    }

    public async Task Add(Pessoa pessoa){
        await Task.Run(() => pessoas.Add(pessoa.Id, pessoa));
    }

    public async Task Edit(Pessoa pessoa){
        await Task.Run(() =>
        {
            pessoas.Remove(pessoa.Id);
            pessoas.Add(pessoa.Id, pessoa);
        });
    }

    public async Task Delete(int id){
        await Task.Run(() => pessoas.Remove(id));
    }
}

```

## Implementando o padrão Command

Para gerenciar as interações dos objetos, a biblioteca MediatR implementa o padrão Command. Este padrão específica um objeto que encapsula toda informação necessária para executar uma ação posterior.

É neste ponto que a biblioteca faz uso do CQRS, como explicado anteriormente. Como vimos, no CQRS as operações são separadas em queries e commands. A parte dos commands é uma aplicação do padrão Command, que na implementação do MediatR é composta de dois objetos: **Command** e **Command Handler**.

Os objetos **Command** definem solicitações que irão alterar o estado dos dados e que o sistema precisa realizar. Por ser imperativo e se tratar de uma ação que será executada apenas uma vez (por solicitação) é recomendado que esses objetos sejam nomeados com o verbo no imperativo: “cadastra”, “altera”, etc. Também se recomenda a adição de um tipo, e.g., `CadastraPessoaCommand`, `AlteraPessoaCommand`, etc.

Já os objetos **Command Handler** serão responsáveis por executar as ações definidas pelos objetos **Command**. É aqui que ficará centralizado grande parte da lógica da aplicação.

Vamos iniciar a nossa implementação deste padrão definindo as classes **Command**:

```csharp
public class CadastraPessoaCommand : IRequest
{
    public string Nome { get; set; }
    public int Idade { get; set; }
    public char Sexo { get; set; }
}

```

```csharp
public class AlteraPessoaCommand : IRequest
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public int Idade { get; set; }
    public char Sexo { get; set; }
}

```

```csharp
public class ExcluiPessoaCommand : IRequest
{
    public int Id { get; set; }
}

```

Note que essas são classes POCO simples, que contém apenas os atributos necessários para executar a ação especificada. Todas implementam a interface `IRequest` da biblioteca MediatR.

Nesta interface genérica se especifica o tipo de dado que será retornado quando o command for processado. Também é atráves do uso desta interface que será possível vincular os commands com as classes Command Handlers. É desta forma que a biblioteca saberá qual objeto deve ser invocado quando uma solicitação for gerada.

As boas práticas recomendam que para cada objeto Command haja um objeto Command Handler, entretanto seria possível implementar um objeto Command Handler para lidar com todos os commands definidos na aplicação.

Para este exemplo vou seguir as boas práticas, então a aplicação conterá as três classes abaixo:

```csharp
public class CadastraPessoaCommandHandler : IRequestHandler
{
    private readonly IMediator _mediator;
    private readonly IRepository _repository;
    public CadastraPessoaCommandHandler(IMediator mediator, IRepository repository)
    {
        this._mediator = mediator;
        this._repository = repository;
    }

    public async Task Handle(CadastraPessoaCommand request, CancellationToken cancellationToken)
    {
        var pessoa = new Pessoa { Nome = request.Nome, Idade = request.Idade, Sexo = request.Sexo };

        try {
            pessoa = await _repository.Add(pessoa);

            await _mediator.Publish(new PessoaCriadaNotification { Id = pessoa.Id, Nome = pessoa.Nome, Idade = pessoa.Idade, Sexo = pessoa.Sexo});

            return await Task.FromResult("Pessoa criada com sucesso");
        } catch(Exception ex) {
            await _mediator.Publish(new PessoaCriadaNotification { Id = pessoa.Id, Nome = pessoa.Nome, Idade = pessoa.Idade, Sexo = pessoa.Sexo });
            await _mediator.Publish(new ErroNotification { Excecao = ex.Message, PilhaErro = ex.StackTrace });
            return await Task.FromResult("Ocorreu um erro no momento da criação");
        }

    }
}

```

```csharp
public class AlteraPessoaCommandHandler : IRequestHandler
{
    private readonly IMediator _mediator;
    private readonly IRepository _repository;
    public AlteraPessoaCommandHandler(IMediator mediator, IRepository repository)
    {
        this._mediator = mediator;
        this._repository = repository;
    }

    public async Task Handle(AlteraPessoaCommand request, CancellationToken cancellationToken)
    {
        var pessoa = new Pessoa { Id = request.Id, Nome = request.Nome, Idade = request.Idade, Sexo = request.Sexo };

        try {
            await _repository.Edit(pessoa);

            await _mediator.Publish(new PessoaAlteradaNotification { Id = pessoa.Id, Nome = pessoa.Nome, Idade = pessoa.Idade, Sexo = pessoa.Sexo, IsEfetivado = true});

            return await Task.FromResult("Pessoa alterada com sucesso");
        } catch(Exception ex) {
            await _mediator.Publish(new PessoaAlteradaNotification { Id = pessoa.Id, Nome = pessoa.Nome, Idade = pessoa.Idade, Sexo = pessoa.Sexo, IsEfetivado = false});
            await _mediator.Publish(new ErroNotification { Excecao = ex.Message, PilhaErro = ex.StackTrace });
            return await Task.FromResult("Ocorreu um erro no momento da alteração");
        }

    }
}

```

```csharp
namespace MediatRSample.Application.Handlers
{
    public class ExcluiPessoaCommandHandler : IRequestHandler
    {
        private readonly IMediator _mediator;
        private readonly IRepository _repository;
        public ExcluiPessoaCommandHandler(IMediator mediator, IRepository repository)
        {
            this._mediator = mediator;
            this._repository = repository;
        }

        public async Task Handle(ExcluiPessoaCommand request, CancellationToken cancellationToken)
        {
            try {
                await _repository.Delete(request.Id);

                await _mediator.Publish(new PessoaExcluidaNotification { Id = request.Id, IsEfetivado = true});

                return await Task.FromResult("Pessoa excluída com sucesso");
            } catch(Exception ex) {
                await _mediator.Publish(new PessoaExcluidaNotification { Id = request.Id, IsEfetivado = false });
                await _mediator.Publish(new ErroNotification { Excecao = ex.Message, PilhaErro = ex.StackTrace });
                return await Task.FromResult("Ocorreu um erro no momento da exclusão");
            }

        }
    }
}

```

Note que todos os command handlers implementam a interface `IRequestHandler`, nesta interface é especificado uma classe command e o tipo de retorno. Quando esta classe command gerar uma solicitação, o MediatR irá invocar o command handler, chamando o método `Handler`.

É no método `Handler` que definimos as instruções que devem ser realizadas para aplicar a solicitação definida pelo command.

Após a solicitação ser atendida, é possível utilizar o método `Publish()` para emitir uma notificação para todo sistema. Onde o MediatR irá procurar por uma a classe que tenha implementado a interface `INotificationHandler` e invocar o método `Handler()` para processar aquela notificação, como veremos a seguir.

## Implementando notificações

Na sua essência as solicitações command não retornam nenhuma informação, assim para ser informado que a solicitação foi finalizada com sucesso, ou não, pode ser implementada notificações.

Como vimos no tópico anterior, no método `Handler` de uma classe Command Handler, pode ser invocado o método `Publish()`, passando por parâmetro um objeto notificação. Todos os Event Handlers que estiverem “ouvindo” notificações do tipo do objeto “publicado” serão notificados e poderão processá-lo.

Assim, para implementar as notificações inicialmente é necessário definir os objetos notificação:

```csharp
public class PessoaCriadaNotification : INotification
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public int Idade { get; set; }
    public char Sexo { get; set; }
}

```

```csharp
public class PessoaAlteradaNotification : INotification
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public int Idade { get; set; }
    public char Sexo { get; set; }
    public bool IsEfetivado { get; set; }
}

```

```csharp
public class PessoaExcluidaNotification : INotification
{
    public int Id { get; set; }
    public bool IsEfetivado { get; set; }
}

```

```csharp
public class ErroNotification : INotification
{
    public string Excecao { get; set; }
    public string PilhaErro { get; set; }
}

```

Como as classes Commands, as notificações são classes POCO que contêm apenas os dados necessários para processar a informação. Para que a biblioteca reconheça o objeto dessas classes como uma notificação é importante que elas implementem a interface `INotification`.

Já a nossa classe Notification Handler irá “escutar” todas as notificações, pois todas serão apenas registradas no console:

```csharp
public class LogEventHandler :
                            INotificationHandler,
                            INotificationHandler,
                            INotificationHandler,
                            INotificationHandler
{
    public Task Handle(PessoaCriadaNotification notification, CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            Console.WriteLine($"CRIACAO: '{notification.Id} - {notification.Nome} - {notification.Idade} - {notification.Sexo}'");
        });
    }

    public Task Handle(PessoaAlteradaNotification notification, CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            Console.WriteLine($"ALTERACAO: '{notification.Id} - {notification.Nome} - {notification.Idade} - {notification.Sexo} - {notification.IsEfetivado}'");
        });
    }

    public Task Handle(PessoaExcluidaNotification notification, CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            Console.WriteLine($"EXCLUSAO: '{notification.Id} - {notification.IsEfetivado}'");
        });
    }

    public Task Handle(ErroNotification notification, CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            Console.WriteLine($"ERRO: '{notification.Excecao} \n {notification.PilhaErro}'");
        });
    }
}

```

A aplicação poderia definir quantas classes Notification Handlers forem necessárias. Por exemplo, além da classe acima poderia haver uma classe que enviaria um e-mail para o usuário informando que uma pessoa foi cadastrada. Outra que avisaria a equipe de suporte que um erro foi gerado.

Caso uma notificação seja “ouvida” por mais de um Notification Handlers, todos serão invocados quando a notificação for gerada.

## Controller e configuração MediatR

Agora que os objetos do MediatR estão criados, podemos definir o nosso controller:

```csharp
[ApiController]
[Route("[controller]")]
public class PessoaController : ControllerBase
{

    private readonly IMediator _mediator;
    private readonly IRepository _repository;

    public PessoaController(IMediator mediator, IRepository repository)
    {
        this._mediator = mediator;
        this._repository = repository;
    }

    [HttpGet]
    public async Task Get()
    {
        return Ok(await _repository.GetAll());
    }

    [HttpGet("{id}")]
    public async Task Get(int id)
    {
        return Ok(await _repository.Get(id));
    }

    [HttpPost]
    public async Task Post(CadastraPessoaCommand command)
    {
        var response = await _mediator.Send(command);
        return Ok(response);
    }

    [HttpPut]
    public async Task Put(AlteraPessoaCommand command)
    {
        var response = await _mediator.Send(command);
        return Ok(response);
    }

    [HttpDelete("{id}")]
    public async Task Delete(int id)
    {
        var obj = new ExcluiPessoaCommand { Id = id };
        var result = await _mediator.Send(obj);
        return Ok(result);
    }
}

```

Note que neste controller estamos “injetando” a interface `IMediator`, isso foi feito para que seja possível enviar as solicitações dos nossos objetos command com o método `Send` que esta interface disponibiliza:

```csharp
var response = await _mediator.Send(command);

```

Neste contexto, o `IMediator` será a classe mediadora que através do método `Send` chama os command handlers que definimos, com base no objeto passado.

Por fim, é necessário adicionar o MediatR como serviço da nossa aplicação no método `ConfigureServices` da classe `Startup`:

```csharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddMediatR(typeof(Startup));
    services.AddSingleton();
}

```

Também repare que estamos registrando a nossa classe repositório para que ela seja “injetada” no nosso controller e nas classes Command Handlers.

## E a mágica acontece

Com a nossa aplicação definida, podemos iniciá-la e testar os endpoints. Note que ao executar uma solicitação:

![Tela no Postman, mostrando o exemplo de uma requisição POST para o endpoint “https://localhost:5001/pessoa”](https://dkrn4sk0rn31v.cloudfront.net/2020/05/05142041/exemplo-endpoint-post-criacao-pessoa.png)

Ela será registrada no console:

![Print do terminal do Visual Studio Code mostrando o texto: “CRIACAO: ‘1 - Carlos - 21 - M’”](https://dkrn4sk0rn31v.cloudfront.net/2020/05/05142345/console-visual-code-log-criacao-pessoa.png)

Todas as solicitações que realizam alguma alteração nos dados serão registradas:

![Print do terminal do Visual Studio Code mostrando logs do endpoint](https://dkrn4sk0rn31v.cloudfront.net/2020/05/05142435/console-visual-code-log-varias-acoes.png)

Você pode ver o código completo da aplicação no [repositório dela no meu Github](https://github.com/wladimilson/MediatRSample).

[  ![C# (C Sharp) Avançado](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp.svg)   Curso C# (C Sharp) Avançado Conhecer o curso ](https://www.treinaweb.com.br/curso/csharp-avancado)

## No episódio de hoje aprendemos…

Mesmo com o exemplo simples demonstrado neste artigo, é possível notar que o Mediator Pattern nos ajuda a manter os objetos do sistema totalmente isolados e independentes, cada um possuindo apenas a sua responsabilidade.

Com a biblioteca MediatR a implementação deste padrão em uma aplicação ASP.NET Core é facilitada. Mas é importante frisar que este o Mediator não deve ser utilizado em qualquer projeto, dependendo do caso, a “sobrecarga “ necessária para implementá-lo não compensará os benefícios que fornece.

Então como He-Man diria, utilize com sabedoria.

- [ #C# ](https://www.treinaweb.com.br/blog/tag/csharp)
- [ #ASP.NET ](https://www.treinaweb.com.br/blog/tag/asp-net)
- [ #ASP .NET Core ](https://www.treinaweb.com.br/blog/tag/asp-net-core)
- [ #Web API ](https://www.treinaweb.com.br/blog/tag/web-api)
- [ #Mediator Pattern ](https://www.treinaweb.com.br/blog/tag/mediator-pattern)
- [ #CQRS ](https://www.treinaweb.com.br/blog/tag/cqrs)
- [ #Command Pattern ](https://www.treinaweb.com.br/blog/tag/command-pattern)
- [ #MediatR ](https://www.treinaweb.com.br/blog/tag/mediatr)

Autor

 ![Wladimilson M. Nascimento](//secure.gravatar.com/avatar/f0dd442f156a3eacd2880e9cd0eafbd1?d=mm)

## Wladimilson M. Nascimento

 Instrutor, nerd, cinéfilo e desenvolvedor nas horas vagas. Graduado em Ciências da Computação pela Universidade Metodista de São Paulo. 

 [Todos os artigos](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento)  

## Continue estudando

 Transforme leitura em prática com os cursos e formações da TreinaWeb.

 [Ver cursos](https://www.treinaweb.com.br/cursos)   

  Continue lendo

## Artigos relacionados

- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/05/padr-es-projetos-400x280.jpg)  [ Padrões de Projeto ](https://www.treinaweb.com.br/blog/categoria/padroes-de-projeto) 

     10 anos atrás

    ##  [ Padrões de projeto: o que são e o que resolvem ](https://www.treinaweb.com.br/blog/padroes-de-projeto-o-que-sao-e-o-que-resolvem) 

     Design Patterns (Padrões de Projeto) são soluções para problemas comuns que encontramos no desenvolvimento ou manutenção de um software.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/02/c-sharp-consumindo-apis-com-flurl-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# - Testando requisições com Flurl ](https://www.treinaweb.com.br/blog/c-testando-requisicoes-com-flurl) 

     Implemente testes unitários em requisições HTTP com o auxílio de Flurl.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/02/c-sharp-consumindo-apis-com-flurl-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# - Consumindo APIs com Flurl ](https://www.treinaweb.com.br/blog/c-consumindo-apis-com-flurl) 

     Veja como consumir dados de uma API no C#, utilizando a biblioteca Flurl.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/11/C-SHARP-PROPRIEDADES-INIT-RECORD-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# 9.0 - Inteiros nativos e inferência de tipos ](https://www.treinaweb.com.br/blog/c-9-0-inteiros-nativos-e-inferencia-de-tipos) 

     Conheça os novos tipos de dados introduzidos no C# 9.0, os inteiros nativos e os novos recursos da inferência de tipos.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/11/C-SHARP-PROPRIEDADES-INIT-RECORD-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# 9.0 - Programas top-level e Pattern Matching ](https://www.treinaweb.com.br/blog/c-9-0-programas-top-level-e-pattern-matching) 

     Dando continuidade ao nosso estudo do C# 9.0, neste artigo veremos dois novos recursos dele: Programas top-leve e Pattern Matching.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/11/C-SHARP-PROPRIEDADES-INIT-RECORD-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# 9.0 - Propriedades init e record ](https://www.treinaweb.com.br/blog/c-9-0-propriedades-init-e-record) 

     Já estamos no C# 9.0, a nova versão lançada no .NET Conf 2020 trouxe uma série de novos recursos, veja neste artigo dois deles: propriedades init e record.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/05/como-instalar-o-csharp-e-nosso-primeiro-exemplo-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     4 anos atrás

    ##  [ Guia da linguagem C# ](https://www.treinaweb.com.br/blog/guia-da-linguagem-csharp) 

     Nesse guia de C# você aprenderá o necessário para criar os seus primeiros softwares com a linguagem de programação C#. Acesse agora mesmo!

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/05/como-instalar-o-csharp-e-nosso-primeiro-exemplo-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     5 anos atrás

    ##  [ Conhecendo variáveis e constantes no C# ](https://www.treinaweb.com.br/blog/conhecendo-variaveis-e-constantes-no-csharp) 

     Conheça neste artigo os tipos de dados presentes no C# e a sintaxe para que possamos declarar variáveis e constantes.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/05/como-instalar-o-csharp-e-nosso-primeiro-exemplo-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     5 anos atrás

    ##  [ Como instalar o C# e nosso primeiro exemplo ](https://www.treinaweb.com.br/blog/como-instalar-o-csharp-e-nosso-primeiro-exemplo) 

     Neste artigo veremos como instalar o C# nos sistemas Windows, Linux e MacOS e também veremos como escrever nosso primeiro programa.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2017/08/java-csharp-ou-php-qual-linguagem-escolher-400x280.jpg)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     9 anos atrás

    ##  [ Java, C# ou PHP: qual linguagem escolher? ](https://www.treinaweb.com.br/blog/java-csharp-ou-php-qual-linguagem-escolher) 

     Qual linguagem escolher? Java, C# ou PHP? Quais são as vantagens de cada uma? Vamos analisar estas dúvidas que são comuns para quem está começando.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/05/como-instalar-o-csharp-e-nosso-primeiro-exemplo-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     4 anos atrás

    ##  [ Orientação a objetos no C# ](https://www.treinaweb.com.br/blog/orientacao-a-objetos-no-csharp) 

     Aprenda como trabalhar com classes, atributos, métodos e objetos no C# e aumente seus conhecimentos nessa linguagem incrível!

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/03/criando-uma-aplicacao-c-com-gtk-no-codeblocks-400x280.png)  [ C ](https://www.treinaweb.com.br/blog/categoria/c) 

     6 anos atrás

    ##  [ Criando uma aplicação C com GTK no Code::Blocks ](https://www.treinaweb.com.br/blog/criando-uma-aplicacao-c-com-gtk-no-codeblocks) 

     Veja como configurar o GTK no Code::Blocks e passe a utilizar esta IDE para criar seus projetos em C com interfaces gráficas.

     Ler artigo

## Um ano de acesso total para você viver de programação.

 Todos os cursos e formações da TreinaWeb numa única assinatura, com professores que atuam no mercado, suporte direto e certificados. Do primeiro `console.log` ao mercado de trabalho.

- **1 ano** de acesso a **todos os cursos**
- Cursos novos **toda semana**
- Suporte **direto com professores**
- Plano de carreira **personalizado**
- **Certificados digitais** inclusos
- **Aplicativos** para Android e iOS, com **acesso offline**

    **Garantia incondicional de satisfação** 

 Teste por 7 dias e, se não fizer sentido para você, devolvemos seu dinheiro.

### Acesso completo a todos os cursos e dezenas de Formações.

 12 meses 

  Economize R$ 840,00  54% OFF 

 de 12x R$ 129,00 por apenas

 12x  R$ 59,00

 sem juros no cartão de crédito ou R$ 599,00 à vista

  Oferta termina em  **14h 52min 07s**

- Acesso imediato e ilimitado durante 1 ano.
- Plano de carreira personalizado.
- Suporte direto com professores.
- E muito mais!

 [Matricule-se agora](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26)

     [                ](https://www.treinaweb.com.br)

 Escola online de programação, tecnologia e IA.

- [  ](https://www.facebook.com/TreinaWeb/)
- [  ](https://www.instagram.com/treinaweb/)
- [  ](https://www.youtube.com/user/TreinaWeb)
- [  ](https://twitter.com/treinaweb)
- [  ](https://www.linkedin.com/company/treinaweb)
- [  ](https://github.com/treinaweb)

## Inscreva-se em nossa newsletter

Receba lançamentos, promoções e novidades.

   Seu nome     Seu WhatsApp     Seu melhor e-mail   Inscrever-se 

## Cursos

- [ Base para Devs ](https://www.treinaweb.com.br/categoria/base-para-devs)
- [ Front-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-front-end)
- [ Back-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-back-end)
- [ Mobile ](https://www.treinaweb.com.br/categoria/desenvolvimento-mobile)
- [ Bancos de Dados ](https://www.treinaweb.com.br/categoria/bancos-de-dados)
- [ Cloud ](https://www.treinaweb.com.br/categoria/cloud-computing)
- [ IA ](https://www.treinaweb.com.br/categoria/ia)
- [ E mais ](https://www.treinaweb.com.br/categoria/e-mais)
- [ Ver todos os cursos ](https://www.treinaweb.com.br/cursos)

## Conteúdo

- [ Formações ](https://www.treinaweb.com.br/formacoes)
- [ Projetos práticos ](https://www.treinaweb.com.br/projetos-praticos)
- [ Direto ao ponto ](https://www.treinaweb.com.br/direto-ao-ponto)
- [ Planos ](https://www.treinaweb.com.br#assinatura)
- [ Depoimentos ](https://www.treinaweb.com.br#depoimentos)
- [ Comunidade ](https://www.treinaweb.com.br#comunidade)
- [ Corpo docente ](https://www.treinaweb.com.br#docente)

## A empresa

- [ Sobre a TreinaWeb ](https://www.treinaweb.com.br#sobre)
- [ Perguntas frequentes ](https://www.treinaweb.com.br#faq)
- [ Vantagens de estudar na TreinaWeb ](https://www.treinaweb.com.br/vantagens-de-estudar-na-treinaweb)
- [ Cursos para empresas ](https://www.treinaweb.com.br/empresas)
- [ Sugira um novo curso ](https://www.treinaweb.com.br/sugerir-curso)
- [ Trabalhe conosco ](https://www.treinaweb.com.br/trabalhe-conosco)
- [ Artigos ](https://www.treinaweb.com.br/blog)
- [ Desenvolvedores e agentes ](https://www.treinaweb.com.br/developers)
- [ Contato ](https://www.treinaweb.com.br/contato)
- [ Política de privacidade ](https://www.treinaweb.com.br/politica-de-privacidade)
- [ Termos de uso ](https://www.treinaweb.com.br/termos-de-uso)

## Baixe nosso aplicativo

 [   Disponível na **App Store**  ](https://apps.apple.com/us/app/treinaweb/id1322729447) [   Disponível no **Google Play**  ](https://play.google.com/store/apps/details?id=br.com.treinaweb.mobile) 

  Av. Paulista, 1765, Conj 71 e 72 · Bela Vista · São Paulo · SP · 01311-200   © 2004 – 2026 TreinaWeb Tecnologia LTDA · CNPJ 06.156.637/0001-58
