├── .github
└── workflows
│ └── dotnet-core.yml
├── .gitignore
├── Apresentação
└── Aplicando design patterns na prática com C#.pdf
├── README.md
├── src
├── Application
│ ├── Application.csproj
│ ├── DTO
│ │ ├── DebitoVeiculo.cs
│ │ └── Veiculo.cs
│ ├── Decorators
│ │ ├── DetranVerificadorDebitosDecoratorCache.cs
│ │ └── DetranVerificadorDebitosDecoratorLogger.cs
│ ├── Implementations
│ │ └── DetranVerificadorDebitosServices.cs
│ ├── Repository
│ │ ├── IDetranVerificadorDebitosFactory.cs
│ │ └── IDetranVerificadorDebitosRepository.cs
│ └── Services
│ │ └── IDetranVerificadorDebitosService.cs
├── DesignPatternSamples.sln
├── Domain
│ ├── Domain.csproj
│ └── Repository
│ │ └── IDetranVerificadorDebitos.cs
├── Infra.Repository.Detran.Tests
│ ├── DependencyInjectionFixture.cs
│ ├── DetranVerificadorDebitosFactoryTests.cs
│ ├── Infra.Repository.Detran.Tests.csproj
│ └── appsettings.json
├── Infra.Repository.Detran
│ ├── DetranPEVerificadorDebitosRepository.cs
│ ├── DetranRJVerificadorDebitosRepository.cs
│ ├── DetranRSVerificadorDebitosRepository.cs
│ ├── DetranSPVerificadorDebitosRepository.cs
│ ├── DetranVerificadorDebitosFactory.cs
│ ├── DetranVerificadorDebitosRepositoryCrawlerBase.cs
│ └── Infra.Repository.Detran.csproj
├── WebAPI
│ ├── Controllers
│ │ └── Detran
│ │ │ └── DebitosController.cs
│ ├── Mapper
│ │ └── DetranMapper.cs
│ ├── Middlewares
│ │ └── ExceptionHandlingMiddleware.cs
│ ├── Models
│ │ ├── AbstractResultModel.cs
│ │ ├── Detran
│ │ │ ├── DebitoVeiculoModel.cs
│ │ │ └── VeiculoModel.cs
│ │ ├── FailureResultModel.cs
│ │ ├── IResultModel.cs
│ │ ├── ResultDetail.cs
│ │ └── SuccessResultModel.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── WebAPI.csproj
│ └── appsettings.json
├── Workbench.Comparer
│ ├── GenericComparerFactory.cs
│ └── Workbench.Comparer.csproj
├── Workbench.DependencyInjection.Extensions
│ ├── ServiceCollectionExtensions.cs
│ └── Workbench.DependencyInjection.Extensions.csproj
├── Workbench.GenericComparer.Tests
│ ├── GenericComparerFactoryTest.cs
│ ├── Workbench.GenericComparer.Tests.csproj
│ └── coverage.json
├── Workbench.IDistributedCache.Extensions
│ ├── IDistributedCacheExtensions.cs
│ └── Workbench.IDistributedCache.Extensions.csproj
├── Workbench.IFormatter.Extensions.Tests
│ ├── IFormaterExtensionsTests.cs
│ └── Workbench.IFormatter.Extensions.Tests.csproj
├── Workbench.IFormatter.Extensions
│ ├── IFormatterExtensions.cs
│ └── Workbench.IFormatter.Extensions.csproj
├── Workbench.Linq.Extensions.Tests
│ ├── DistinctExtensionsTests.cs
│ └── Workbench.Linq.Extensions.Tests.csproj
└── Workbench.Linq.Extensions
│ ├── DistinctExtensions.cs
│ └── Workbench.Linq.Extensions.csproj
└── test-coverage.bat
/.github/workflows/dotnet-core.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core
2 |
3 | on:
4 | push:
5 | branches: [ main, develop ]
6 | pull_request: [ main ]
7 | jobs:
8 | build:
9 |
10 | runs-on: ubuntu-latest
11 | env:
12 | working-directory: ./src
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 |
17 | - name: Setup .NET Core
18 | uses: actions/setup-dotnet@v1
19 | with:
20 | dotnet-version: 3.1.301
21 |
22 | - name: Install dependencies
23 | working-directory: ${{env.working-directory}}
24 | run: dotnet restore
25 |
26 | - name: Build
27 | working-directory: ${{env.working-directory}}
28 | run: dotnet build --configuration Release --no-restore
29 |
30 | - name: Test
31 | working-directory: ${{env.working-directory}}
32 | run: dotnet test --no-restore --verbosity normal
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Visual Studio
2 | .vs/
3 | [Bb]in/
4 | [Oo]bj/
5 | *.user
6 | TestResults/
7 |
8 | # VS Code
9 | .vscode/
10 |
11 | # Testes de Cobertura
12 | CoverageResults
13 |
14 | # Sonar
15 | .sonarqube
16 | test-coverage-with-sonar.bat
--------------------------------------------------------------------------------
/Apresentação/Aplicando design patterns na prática com C#.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fructuoso/DesignPatternSamples/7eafc0492b3e8dd89c4492f763a56a35887d8c01/Apresentação/Aplicando design patterns na prática com C#.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DesignPatternSamples
2 | |Branch|Build|
3 | |-:|-|
4 | |Develop||
5 | |Main||
6 |
7 | Aplicação de exemplo de aplicação de Design Patterns na prática em um projeto WebAPI .NET Core 3.1 utilizada na palestra "Aplicando design patterns na prática com C#" ([Link Apresentação](Apresenta%C3%A7%C3%A3o/Aplicando%20design%20patterns%20na%20pr%C3%A1tica%20com%20C%23.pdf))
8 |
9 | ## Testes de Cobertura
10 |
11 | Passo a passo sobre como executar os testes unitários (e calcular o code coverage) localmente antes de realizar o commit.
12 |
13 | Obs.: O VS2019 possui esta funcionalidade nativamente, porém ela só está habilitada para a versão Enterprise segundo a [documentação](https://docs.microsoft.com/pt-br/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested?view=vs-2019) da própria Microsoft.
14 |
15 | ### Pré-Requisitos
16 |
17 | Para gerar o relatório é necessário instalar o **dotnet-reportgenerator-globaltool**
18 |
19 | ```script
20 | dotnet tool install --global dotnet-reportgenerator-globaltool --version 4.6.1
21 | ````
22 |
23 | ### Execução
24 |
25 | Executar o **.bat** para realizar a execução dos testes automatizados com a extração do relatório de cobertura na sequência.
26 |
27 | ```bat
28 | $ test-coverage.bat
29 | ```
30 |
31 | ## Padrões na Prática
32 |
33 | ### Strategy
34 |
35 | #### Problema:
36 |
37 | Nosso objetivo é Utilizar o método Distinct do System.Linq, este por sua vez espera como entrada uma IEqualityComparer. Isso por si só já representa uma implementação de Strategy, entretanto nós não queremos criar uma única implementação engessada que nos permita comparar um determinado objeto de uma única forma.
38 |
39 | ##### Solução:
40 |
41 | 1. Criar uma classe que implemente a interface [IEqualityComparer](https://docs.microsoft.com/pt-br/dotnet/api/system.collections.generic.iequalitycomparer-1?view=netcore-3.1);
42 | 2. Esta classe deve receber o 'como' os objetos deverão ser comparados através de um parâmetro, que neste caso é uma função anônima;
43 |
44 | Desta forma a classe que criamos sabe comparar objetos, porém ela não sabe os critérios que serão utilizados, os critérios serão injetados através de uma função anônima.
45 |
46 | [Implementação](src/Workbench.Comparer/GenericComparerFactory.cs)\
47 | [Consumo](src/Workbench.GenericComparer.Tests/GenericComparerFactoryTest.cs#L27)
48 |
49 | Podemos tornar o consumo ainda mais interessante criando uma *Sugar Syntax* através de métodos de extensão.
50 |
51 | [Implementação](src/Workbench.Linq.Extensions/DistinctExtensions.cs)\
52 | [Consumo](src/Workbench.Linq.Extensions.Tests/DistinctExtensionsTests.cs#L26)
53 |
54 | Desta forma através do padrão [Strategy](#strategy) estamos aderentes ao princípio **Aberto-Fechado** e **Inversão de Controle**.
55 |
56 | ### Factory
57 |
58 | #### Problema:
59 |
60 | Nós queremos criar um serviço de consulta de débitos do veículo que seja capaz de acessar o sistema do DETRAN e obter estas informações, porém o DETRAN possui uma aplicação completamente diferente de acordo com o estado.
61 |
62 | Nós não queremos modificar o nosso serviço sempre que um novo estado for implementado.
63 |
64 | #### Solução:
65 |
66 | 1. Criar uma interface que determine uma assinatura única para o serviço;
67 | 2. Realizar uma implementação para cada um dos estados;
68 | 3. Criar uma classe Factory, onde sua responsabilidade será determinar qual classe concreta deverá ser instanciada;
69 |
70 | [Implementação](src/Infra.Repository.Detran/DetranVerificadorDebitosFactory.cs)\
71 | [Consumo](src/Application/Implementations/DetranVerificadorDebitosServices.cs#L20)\
72 | [Teste](src/Infra.Repository.Detran.Tests/DetranVerificadorDebitosFactoryTests.cs#L22)
73 |
74 | Desta forma através do padrão [Factory](#factory) estamos aderentes ao princípio **Aberto-Fechado**.
75 |
76 | Neste exemplo o nosso [Factory](#factory) ainda está diretamente relacionado ao princípio **Substituição de Liskov**.
77 |
78 | ### Singleton
79 |
80 | #### Problema:
81 |
82 | Visto que o nosso Factory tem como responsabilidade apenas identificar a classe concreta que teve ser inicializada a partir de um Setup pré-estabelecido no [Startup](src/WebAPI/Startup.cs#L130) da aplicação, não faz sentido que ele seja instanciado a cada solicitação.
83 |
84 | #### Solução:
85 |
86 | Como estamos fazendo uso da Injeção de Dependência nativa do .Net Core processo se torna mais simples:
87 |
88 | 1. Modificar o registro no Startup para que o serviço seja registrado como Singleton.
89 |
90 | [Implementação](src/WebAPI/Startup.cs#L111)
91 |
92 | Com isso nós temos uma única instância sendo inicializada e configurada no [Startup](src/WebAPI/Startup.cs#L130) da aplicação.
93 |
94 | ### Template Method
95 |
96 | #### Problema:
97 |
98 | Visto que em algum momento iremos implementar 27 serviços diferentes para acessar os DETRAN que temos espalhados pelo Brasil.
99 |
100 | Entendemos que, mesmo que, os sites sejam diferentes, os passos necessários para extrair a informação costumam ser semelhantes:
101 |
102 | * Consultar Site
103 | * Consolidar Resultado
104 |
105 | Como a nossa interface [IDetranVerificadorDebitosRepository](src/Application/Repository/IDetranVerificadorDebitosRepository.cs) possui apenas o método ConsultarDebitos, nosso código corre risco de não ficar padronizado e ainda perdermos o princípio da **Responsabilidade Única**.
106 |
107 | #### Solução:
108 |
109 | 1. Criar uma classe abstrata com métodos mais específicos para realizar o trabalho desejado;
110 | 2. A classe abstrata 'deve' implementar o método exposto pela Interface;
111 | 3. Ao invés das classes implementarem a Interface, elas herdarão o comportamento da classe abstrata, implementando apenas os métodos mais específicos.
112 |
113 | Com isso torna-se mais fácil:
114 | * Dividir o trabalho;
115 | * Testar o código.
116 |
117 | [Implementação](src/Infra.Repository.Detran/DetranVerificadorDebitosRepositoryCrawlerBase.cs)\
118 | [Consumo](src/Infra.repository.detran/DetranPEVerificadorDebitosRepository.cs)
119 |
120 | O neste exemplo o nosso [Template Method](#template-method) ainda seguindo o princípio **Segregação da Interface**, onde os métodos específicos foram adicionados na nossa classe abstrata [DetranVerificadorDebitosRepositoryCrawlerBase](src/Repository.Detran/../Infra.Repository.Detran/DetranVerificadorDebitosRepositoryCrawlerBase.cs), desta forma conseguimos atingir também o princípio de **Substituição de Liskov**.
121 |
122 | ### Decorator
123 |
124 | #### Problema:
125 |
126 | Com o serviço [DetranVerificadorDebitosServices](src/Application/Implementations/DetranVerificadorDebitosServices.cs) identificamos que precisamos adicionar funcionalidades técnicas a ele (como por exemplo **Log** e **Cache**), porém essas funcionalidades não devem gerar acoplamento no nosso código.
127 |
128 | Então como fazer isso sem quebrar os princípios **Responsabilidade Única** e **Aberto-Fechado**?
129 |
130 | #### Solução:
131 |
132 | Neste cenário estamos usando uma abordagem que nos permite transferir a complexidade de registrar um Decorator no ServiceCollection para um método de extensão.
133 |
134 | Desta forma precisamos:
135 |
136 | 1. Criar uma nova classe concreta que deverá implementar a Interface que será 'decorada';
137 | 2. Implementar nesta nova classe a funcionalidade que gostaríamos de acrescentar ao método em questão;
138 | 3. Adicionar Decorator no Injetor de Dependências fazendo referência à interface que será decorada.
139 |
140 | Obs.: É possível incluir mais de um Decorator, porém é preciso ter ciência de que a ordem em que eles são associados faz diferença no resultado final.
141 |
142 | [Método de Extensão](src/Workbench.DependencyInjection.Extensions/ServiceCollectionExtensions.cs#L10)\
143 | [Implementação](src/Application/Decorators/DetranVerificadorDebitosDecoratorLogger.cs#L23)\
144 | [Registro](src/WebAPI/Startup.cs#L110)
145 |
146 | O Decorator funciona como uma 'Boneca Russa' dessa forma podemos 'empilhar' diversos Decorators em uma mesma Interface.
147 |
148 | Temos o exemplo de um segundo Decorator adicionando o recurso de Cache ao nosso Service.
149 |
150 | [Implementação](src/Application/Decorators/DetranVerificadorDebitosDecoratorCache.cs#L25)\
151 | [Registro](src/WebAPI/Startup.cs#L09)
152 |
153 | Desta forma nós agregamos duas funcionalidades ao nosso serviço sem modificar o comportamento do serviço, ou modificar quem chama o serviço, desta forma estamos aderentes aos princípios **Responsabilidade Única**, **Aberto-Fechado** e **Inversão de Controle**.
154 |
155 | Obs.: Seguir o princípio Segregação de Interfaces pode tornar o seu Decorator mais simples de ser implementado, visto que você terá menos métodos para submeter ao padrão.
--------------------------------------------------------------------------------
/src/Application/Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | DesignPatternSamples.Application
6 | DesignPatternSamples.Application
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Application/DTO/DebitoVeiculo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace DesignPatternSamples.Application.DTO
4 | {
5 | [Serializable]
6 | public class DebitoVeiculo
7 | {
8 | public DateTime DataOcorrencia { get; set; }
9 | public string Descricao { get; set; }
10 | public double Valor { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/DTO/Veiculo.cs:
--------------------------------------------------------------------------------
1 | namespace DesignPatternSamples.Application.DTO
2 | {
3 | public class Veiculo
4 | {
5 | public string Placa { get; set; }
6 | public string UF { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Application/Decorators/DetranVerificadorDebitosDecoratorCache.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using DesignPatternSamples.Application.Services;
3 | using Microsoft.Extensions.Caching.Distributed;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using Workbench.IDistributedCache.Extensions;
7 |
8 | namespace DesignPatternSamples.Application.Decorators
9 | {
10 | public class DetranVerificadorDebitosDecoratorCache : IDetranVerificadorDebitosService
11 | {
12 | private readonly IDetranVerificadorDebitosService _Inner;
13 | private readonly IDistributedCache _Cache;
14 |
15 | private const int DUCACAO_CACHE = 20;
16 |
17 | public DetranVerificadorDebitosDecoratorCache(
18 | IDetranVerificadorDebitosService inner,
19 | IDistributedCache cache)
20 | {
21 | _Inner = inner;
22 | _Cache = cache;
23 | }
24 |
25 | public Task> ConsultarDebitos(Veiculo veiculo)
26 | {
27 | return _Cache.GetOrCreateAsync($"{veiculo.UF}_{veiculo.Placa}", () => _Inner.ConsultarDebitos(veiculo), DUCACAO_CACHE);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Application/Decorators/DetranVerificadorDebitosDecoratorLogger.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using DesignPatternSamples.Application.Services;
3 | using Microsoft.Extensions.Logging;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Threading.Tasks;
7 |
8 | namespace DesignPatternSamples.Application.Decorators
9 | {
10 | public class DetranVerificadorDebitosDecoratorLogger : IDetranVerificadorDebitosService
11 | {
12 | private readonly IDetranVerificadorDebitosService _Inner;
13 | private readonly ILogger _Logger;
14 |
15 | public DetranVerificadorDebitosDecoratorLogger(
16 | IDetranVerificadorDebitosService inner,
17 | ILogger logger)
18 | {
19 | _Inner = inner;
20 | _Logger = logger;
21 | }
22 |
23 | public async Task> ConsultarDebitos(Veiculo veiculo)
24 | {
25 | Stopwatch watch = Stopwatch.StartNew();
26 | _Logger.LogInformation($"Iniciando a execução do método ConsultarDebitos({veiculo})");
27 | var result = await _Inner.ConsultarDebitos(veiculo);
28 | watch.Stop();
29 | _Logger.LogInformation($"Encerrando a execução do método ConsultarDebitos({veiculo}) {watch.ElapsedMilliseconds}ms");
30 | return result;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/Application/Implementations/DetranVerificadorDebitosServices.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using DesignPatternSamples.Application.Repository;
3 | using DesignPatternSamples.Application.Services;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace DesignPatternSamples.Application.Implementations
8 | {
9 | public class DetranVerificadorDebitosServices : IDetranVerificadorDebitosService
10 | {
11 | private readonly IDetranVerificadorDebitosFactory _Factory;
12 |
13 | public DetranVerificadorDebitosServices(IDetranVerificadorDebitosFactory factory)
14 | {
15 | _Factory = factory;
16 | }
17 |
18 | public Task> ConsultarDebitos(Veiculo veiculo)
19 | {
20 | IDetranVerificadorDebitosRepository repository = _Factory.Create(veiculo.UF);
21 | return repository.ConsultarDebitos(veiculo);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Application/Repository/IDetranVerificadorDebitosFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace DesignPatternSamples.Application.Repository
4 | {
5 | public interface IDetranVerificadorDebitosFactory
6 | {
7 | public IDetranVerificadorDebitosFactory Register(string UF, Type repository);
8 | public IDetranVerificadorDebitosRepository Create(string UF);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Application/Repository/IDetranVerificadorDebitosRepository.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace DesignPatternSamples.Application.Repository
6 | {
7 | public interface IDetranVerificadorDebitosRepository
8 | {
9 | Task> ConsultarDebitos(Veiculo veiculo);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Application/Services/IDetranVerificadorDebitosService.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace DesignPatternSamples.Application.Services
6 | {
7 | public interface IDetranVerificadorDebitosService
8 | {
9 | Task> ConsultarDebitos(Veiculo veiculo);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/DesignPatternSamples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30523.141
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAPI", "WebAPI\WebAPI.csproj", "{7BB26546-C696-4A49-BB57-AFFA5F2B6799}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01. Presentation", "01. Presentation", "{8B43F163-AFA9-431D-8B34-13880AC45FEA}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00. Framework", "00. Framework", "{81650748-EE14-4EA6-A5FC-D8CCEB7873D5}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.Comparer", "Workbench.Comparer\Workbench.Comparer.csproj", "{0F78222C-8493-4293-A424-33ADB447CC0C}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.GenericComparer.Tests", "Workbench.GenericComparer.Tests\Workbench.GenericComparer.Tests.csproj", "{4467CDE6-BAC4-4A26-80B7-F0D675971830}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.Linq.Extensions", "Workbench.Linq.Extensions\Workbench.Linq.Extensions.csproj", "{E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.Linq.Extensions.Tests", "Workbench.Linq.Extensions.Tests\Workbench.Linq.Extensions.Tests.csproj", "{D2A54E5D-50DC-44F0-974C-8EC22ADAA064}"
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04. Infra", "04. Infra", "{42A88419-8568-433D-A027-A5853780A83E}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infra.Repository.Detran.Tests", "Infra.Repository.Detran.Tests\Infra.Repository.Detran.Tests.csproj", "{660A2898-16BB-4B50-944C-3D6E06C51646}"
23 | EndProject
24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02. Application", "02. Application", "{FAAF7A15-4496-4D73-9D1A-581C3B230232}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "Application\Application.csproj", "{F18BCE3C-E182-4C8F-A39C-7CEA4853CE73}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infra.Repository.Detran", "Infra.Repository.Detran\Infra.Repository.Detran.csproj", "{3EEE90D9-A054-400C-BFC7-9865C0C2DEE5}"
29 | EndProject
30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.DependencyInjection.Extensions", "Workbench.DependencyInjection.Extensions\Workbench.DependencyInjection.Extensions.csproj", "{E6959B8C-EB09-4288-B84C-8752DD708F41}"
31 | EndProject
32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workbench.IDistributedCache.Extensions", "Workbench.IDistributedCache.Extensions\Workbench.IDistributedCache.Extensions.csproj", "{FD7E1EE8-EF31-4785-B945-1ACDDB5D065F}"
33 | EndProject
34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workbench.IFormatter.Extensions", "Workbench.IFormatter.Extensions\Workbench.IFormatter.Extensions.csproj", "{C08D47C6-A1B0-4680-8854-AA5E20C91415}"
35 | EndProject
36 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workbench.IFormatter.Extensions.Tests", "Workbench.IFormatter.Extensions.Tests\Workbench.IFormatter.Extensions.Tests.csproj", "{95C404BB-1BDD-494D-816B-49F3B260C1DC}"
37 | EndProject
38 | Global
39 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
40 | Debug|Any CPU = Debug|Any CPU
41 | Release|Any CPU = Release|Any CPU
42 | EndGlobalSection
43 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
44 | {7BB26546-C696-4A49-BB57-AFFA5F2B6799}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {7BB26546-C696-4A49-BB57-AFFA5F2B6799}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {7BB26546-C696-4A49-BB57-AFFA5F2B6799}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {7BB26546-C696-4A49-BB57-AFFA5F2B6799}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {0F78222C-8493-4293-A424-33ADB447CC0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {0F78222C-8493-4293-A424-33ADB447CC0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {0F78222C-8493-4293-A424-33ADB447CC0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {0F78222C-8493-4293-A424-33ADB447CC0C}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {4467CDE6-BAC4-4A26-80B7-F0D675971830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {4467CDE6-BAC4-4A26-80B7-F0D675971830}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {4467CDE6-BAC4-4A26-80B7-F0D675971830}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {4467CDE6-BAC4-4A26-80B7-F0D675971830}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E}.Release|Any CPU.Build.0 = Release|Any CPU
60 | {D2A54E5D-50DC-44F0-974C-8EC22ADAA064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {D2A54E5D-50DC-44F0-974C-8EC22ADAA064}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {D2A54E5D-50DC-44F0-974C-8EC22ADAA064}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {D2A54E5D-50DC-44F0-974C-8EC22ADAA064}.Release|Any CPU.Build.0 = Release|Any CPU
64 | {660A2898-16BB-4B50-944C-3D6E06C51646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65 | {660A2898-16BB-4B50-944C-3D6E06C51646}.Debug|Any CPU.Build.0 = Debug|Any CPU
66 | {660A2898-16BB-4B50-944C-3D6E06C51646}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {660A2898-16BB-4B50-944C-3D6E06C51646}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {F18BCE3C-E182-4C8F-A39C-7CEA4853CE73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 | {F18BCE3C-E182-4C8F-A39C-7CEA4853CE73}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 | {F18BCE3C-E182-4C8F-A39C-7CEA4853CE73}.Release|Any CPU.ActiveCfg = Release|Any CPU
71 | {F18BCE3C-E182-4C8F-A39C-7CEA4853CE73}.Release|Any CPU.Build.0 = Release|Any CPU
72 | {3EEE90D9-A054-400C-BFC7-9865C0C2DEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73 | {3EEE90D9-A054-400C-BFC7-9865C0C2DEE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
74 | {3EEE90D9-A054-400C-BFC7-9865C0C2DEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
75 | {3EEE90D9-A054-400C-BFC7-9865C0C2DEE5}.Release|Any CPU.Build.0 = Release|Any CPU
76 | {E6959B8C-EB09-4288-B84C-8752DD708F41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77 | {E6959B8C-EB09-4288-B84C-8752DD708F41}.Debug|Any CPU.Build.0 = Debug|Any CPU
78 | {E6959B8C-EB09-4288-B84C-8752DD708F41}.Release|Any CPU.ActiveCfg = Release|Any CPU
79 | {E6959B8C-EB09-4288-B84C-8752DD708F41}.Release|Any CPU.Build.0 = Release|Any CPU
80 | {FD7E1EE8-EF31-4785-B945-1ACDDB5D065F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
81 | {FD7E1EE8-EF31-4785-B945-1ACDDB5D065F}.Debug|Any CPU.Build.0 = Debug|Any CPU
82 | {FD7E1EE8-EF31-4785-B945-1ACDDB5D065F}.Release|Any CPU.ActiveCfg = Release|Any CPU
83 | {FD7E1EE8-EF31-4785-B945-1ACDDB5D065F}.Release|Any CPU.Build.0 = Release|Any CPU
84 | {C08D47C6-A1B0-4680-8854-AA5E20C91415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
85 | {C08D47C6-A1B0-4680-8854-AA5E20C91415}.Debug|Any CPU.Build.0 = Debug|Any CPU
86 | {C08D47C6-A1B0-4680-8854-AA5E20C91415}.Release|Any CPU.ActiveCfg = Release|Any CPU
87 | {C08D47C6-A1B0-4680-8854-AA5E20C91415}.Release|Any CPU.Build.0 = Release|Any CPU
88 | {95C404BB-1BDD-494D-816B-49F3B260C1DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
89 | {95C404BB-1BDD-494D-816B-49F3B260C1DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
90 | {95C404BB-1BDD-494D-816B-49F3B260C1DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
91 | {95C404BB-1BDD-494D-816B-49F3B260C1DC}.Release|Any CPU.Build.0 = Release|Any CPU
92 | EndGlobalSection
93 | GlobalSection(SolutionProperties) = preSolution
94 | HideSolutionNode = FALSE
95 | EndGlobalSection
96 | GlobalSection(NestedProjects) = preSolution
97 | {7BB26546-C696-4A49-BB57-AFFA5F2B6799} = {8B43F163-AFA9-431D-8B34-13880AC45FEA}
98 | {0F78222C-8493-4293-A424-33ADB447CC0C} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
99 | {4467CDE6-BAC4-4A26-80B7-F0D675971830} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
100 | {E6B214ED-0F85-4D4C-B972-0F81C9F9CB2E} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
101 | {D2A54E5D-50DC-44F0-974C-8EC22ADAA064} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
102 | {660A2898-16BB-4B50-944C-3D6E06C51646} = {42A88419-8568-433D-A027-A5853780A83E}
103 | {F18BCE3C-E182-4C8F-A39C-7CEA4853CE73} = {FAAF7A15-4496-4D73-9D1A-581C3B230232}
104 | {3EEE90D9-A054-400C-BFC7-9865C0C2DEE5} = {42A88419-8568-433D-A027-A5853780A83E}
105 | {E6959B8C-EB09-4288-B84C-8752DD708F41} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
106 | {FD7E1EE8-EF31-4785-B945-1ACDDB5D065F} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
107 | {C08D47C6-A1B0-4680-8854-AA5E20C91415} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
108 | {95C404BB-1BDD-494D-816B-49F3B260C1DC} = {81650748-EE14-4EA6-A5FC-D8CCEB7873D5}
109 | EndGlobalSection
110 | GlobalSection(ExtensibilityGlobals) = postSolution
111 | SolutionGuid = {4A90C331-830A-4D9E-971D-F17899C6CD14}
112 | EndGlobalSection
113 | EndGlobal
114 |
--------------------------------------------------------------------------------
/src/Domain/Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | DesignPatternSamples.Domain
6 | DesignPatternSamples.Domain
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Domain/Repository/IDetranVerificadorDebitos.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace DesignPatternSamples.Domain.Repository.Detran
4 | {
5 | public interface IDetranVerificadorDebitos
6 | {
7 | Task ConsultarDebitos(Veiculo veiculo);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran.Tests/DependencyInjectionFixture.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.Repository;
2 | using DesignPatternSamples.Infra.Repository.Detran;
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using System;
6 |
7 | namespace DesignPatternsSamples.Infra.Repository.Detran.Tests
8 | {
9 | public class DependencyInjectionFixture
10 | {
11 | public readonly IServiceProvider ServiceProvider;
12 |
13 | public DependencyInjectionFixture()
14 | {
15 | var services = new ServiceCollection()
16 | .AddLogging()
17 | .AddTransient()
18 | .AddTransient()
19 | .AddTransient()
20 | .AddTransient()
21 | .AddSingleton();
22 |
23 | #region IConfiguration
24 | services.AddTransient((services) =>
25 | new ConfigurationBuilder()
26 |
27 | .SetBasePath(AppContext.BaseDirectory)
28 | .AddJsonFile("appsettings.json", false, true)
29 | .Build()
30 | );
31 | #endregion
32 |
33 | ServiceProvider = services.BuildServiceProvider();
34 |
35 | ServiceProvider.GetService()
36 | .Register("PE", typeof(DetranPEVerificadorDebitosRepository))
37 | .Register("RJ", typeof(DetranRJVerificadorDebitosRepository))
38 | .Register("SP", typeof(DetranSPVerificadorDebitosRepository))
39 | .Register("RS", typeof(DetranRSVerificadorDebitosRepository));
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran.Tests/DetranVerificadorDebitosFactoryTests.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.Repository;
2 | using DesignPatternSamples.Infra.Repository.Detran;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using System;
5 | using Xunit;
6 |
7 | namespace DesignPatternsSamples.Infra.Repository.Detran.Tests
8 | {
9 | public class DetranVerificadorDebitosFactoryTests : IClassFixture
10 | {
11 | private readonly IDetranVerificadorDebitosFactory _Factory;
12 |
13 | public DetranVerificadorDebitosFactoryTests(DependencyInjectionFixture dependencyInjectionFixture)
14 | {
15 | var serviceProvider = dependencyInjectionFixture.ServiceProvider;
16 | _Factory = serviceProvider.GetService();
17 | }
18 |
19 | [Theory(DisplayName = "Dado um UF que está devidamente registrado no Factory devemos receber a sua implementação correspondente")]
20 | [InlineData("PE", typeof(DetranPEVerificadorDebitosRepository))]
21 | [InlineData("SP", typeof(DetranSPVerificadorDebitosRepository))]
22 | [InlineData("RJ", typeof(DetranRJVerificadorDebitosRepository))]
23 | [InlineData("RS", typeof(DetranRSVerificadorDebitosRepository))]
24 | public void InstanciarServicoPorUFRegistrado(string uf, Type implementacao)
25 | {
26 | var resultado = _Factory.Create(uf);
27 |
28 | Assert.NotNull(resultado);
29 | Assert.IsType(implementacao, resultado);
30 | }
31 |
32 | [Fact(DisplayName = "Dado um UF que não está registrado no Factory devemos receber NULL")]
33 | public void InstanciarServicoPorUFNaoRegistrado()
34 | {
35 | IDetranVerificadorDebitosRepository implementacao = _Factory.Create("CE");
36 |
37 | Assert.Null(implementacao);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran.Tests/Infra.Repository.Detran.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | PreserveNewest
16 | true
17 | PreserveNewest
18 |
19 |
20 |
21 |
22 |
23 | all
24 | runtime; build; native; contentfiles; analyzers; buildtransitive
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | all
36 | runtime; build; native; contentfiles; analyzers; buildtransitive
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran.Tests/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Trace",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranPEVerificadorDebitosRepository.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace DesignPatternSamples.Infra.Repository.Detran
8 | {
9 | public class DetranPEVerificadorDebitosRepository : DetranVerificadorDebitosRepositoryCrawlerBase
10 | {
11 | private readonly ILogger _Logger;
12 |
13 | public DetranPEVerificadorDebitosRepository(ILogger logger)
14 | {
15 | _Logger = logger;
16 | }
17 |
18 | protected override Task> PadronizarResultado(string html)
19 | {
20 | _Logger.LogDebug($"Padronizando o Resultado {html}.");
21 | return Task.FromResult>(new List() { new DebitoVeiculo() { DataOcorrencia = DateTime.UtcNow } });
22 | }
23 |
24 | protected override Task RealizarAcesso(Veiculo veiculo)
25 | {
26 | Task.Delay(5000).Wait(); //Deixando o serviço mais lento para evidenciar o uso do CACHE.
27 | _Logger.LogDebug($"Consultando débitos do veículo placa {veiculo.Placa} para o estado de PE.");
28 | return Task.FromResult("CONTEUDO DO SITE DO DETRAN/PE");
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranRJVerificadorDebitosRepository.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using Microsoft.Extensions.Logging;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace DesignPatternSamples.Infra.Repository.Detran
7 | {
8 | public class DetranRJVerificadorDebitosRepository : DetranVerificadorDebitosRepositoryCrawlerBase
9 | {
10 | private readonly ILogger _Logger;
11 |
12 | public DetranRJVerificadorDebitosRepository(ILogger logger)
13 | {
14 | _Logger = logger;
15 | }
16 |
17 | protected override Task> PadronizarResultado(string html)
18 | {
19 | _Logger.LogDebug($"Padronizando o Resultado {html}.");
20 | return Task.FromResult>(new List() { new DebitoVeiculo() });
21 | }
22 |
23 | protected override Task RealizarAcesso(Veiculo veiculo)
24 | {
25 | _Logger.LogDebug($"Consultando débitos do veículo placa {veiculo.Placa} para o estado de RJ.");
26 | return Task.FromResult("CONTEUDO DO SITE DO DETRAN/RJ");
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranRSVerificadorDebitosRepository.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using Microsoft.Extensions.Logging;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace DesignPatternSamples.Infra.Repository.Detran
7 | {
8 | public class DetranRSVerificadorDebitosRepository : DetranVerificadorDebitosRepositoryCrawlerBase
9 | {
10 | private readonly ILogger _Logger;
11 |
12 | public DetranRSVerificadorDebitosRepository(ILogger logger)
13 | {
14 | _Logger = logger;
15 | }
16 |
17 | protected override Task> PadronizarResultado(string html)
18 | {
19 | _Logger.LogDebug($"Padronizando o Resultado {html}.");
20 | return Task.FromResult>(new List() { new DebitoVeiculo() });
21 | }
22 |
23 | protected override Task RealizarAcesso(Veiculo veiculo)
24 | {
25 | _Logger.LogDebug($"Consultando débitos do veículo placa {veiculo.Placa} para o estado de RS.");
26 | return Task.FromResult("CONTEUDO DO SITE DO DETRAN/RS");
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranSPVerificadorDebitosRepository.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using DesignPatternSamples.Application.Repository;
3 | using Microsoft.Extensions.Logging;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace DesignPatternSamples.Infra.Repository.Detran
8 | {
9 | public class DetranSPVerificadorDebitosRepository : IDetranVerificadorDebitosRepository
10 | {
11 | private readonly ILogger _Logger;
12 |
13 | public DetranSPVerificadorDebitosRepository(ILogger logger)
14 | {
15 | _Logger = logger;
16 | }
17 |
18 | public Task> ConsultarDebitos(Veiculo veiculo)
19 | {
20 | _Logger.LogDebug($"Consultando débitos do veículo placa {veiculo.Placa} para o estado de SP.");
21 | return Task.FromResult>(new List() { new DebitoVeiculo() });
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranVerificadorDebitosFactory.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.Repository;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace DesignPatternSamples.Infra.Repository.Detran
6 | {
7 | public class DetranVerificadorDebitosFactory : IDetranVerificadorDebitosFactory
8 | {
9 | private readonly IServiceProvider _ServiceProvider;
10 | private readonly IDictionary _Repositories = new Dictionary();
11 |
12 | public DetranVerificadorDebitosFactory(IServiceProvider serviceProvider)
13 | {
14 | _ServiceProvider = serviceProvider;
15 | }
16 |
17 | public IDetranVerificadorDebitosRepository Create(string UF)
18 | {
19 | IDetranVerificadorDebitosRepository result = null;
20 |
21 | if (_Repositories.TryGetValue(UF, out Type type))
22 | {
23 | result = _ServiceProvider.GetService(type) as IDetranVerificadorDebitosRepository;
24 | }
25 |
26 | return result;
27 | }
28 |
29 | public IDetranVerificadorDebitosFactory Register(string UF, Type repository)
30 | {
31 | if (!_Repositories.TryAdd(UF, repository))
32 | {
33 | _Repositories[UF] = repository;
34 | }
35 |
36 | return this;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/DetranVerificadorDebitosRepositoryCrawlerBase.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.Application.DTO;
2 | using DesignPatternSamples.Application.Repository;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace DesignPatternSamples.Infra.Repository.Detran
7 | {
8 | public abstract class DetranVerificadorDebitosRepositoryCrawlerBase : IDetranVerificadorDebitosRepository
9 | {
10 | public async Task> ConsultarDebitos(Veiculo veiculo)
11 | {
12 | var html = await RealizarAcesso(veiculo);
13 | return await PadronizarResultado(html);
14 | }
15 |
16 | protected abstract Task RealizarAcesso(Veiculo veiculo);
17 | protected abstract Task> PadronizarResultado(string html);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Infra.Repository.Detran/Infra.Repository.Detran.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | DesignPatternSamples.Infra.Repository.Detran
6 | DesignPatternSamples.Infra.Repository.Detran
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/WebAPI/Controllers/Detran/DebitosController.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using DesignPatternSamples.Application.DTO;
3 | using DesignPatternSamples.Application.Services;
4 | using DesignPatternSamples.WebAPI.Models;
5 | using DesignPatternSamples.WebAPI.Models.Detran;
6 | using Microsoft.AspNetCore.Http;
7 | using Microsoft.AspNetCore.Mvc;
8 | using System.Collections.Generic;
9 | using System.Threading.Tasks;
10 |
11 | namespace DesignPatternSamples.WebAPI.Controllers.Detran
12 | {
13 | [Route("api/Detran/[controller]")]
14 | [ApiController]
15 | public class DebitosController : ControllerBase
16 | {
17 | private readonly IMapper _Mapper;
18 | private readonly IDetranVerificadorDebitosService _DetranVerificadorDebitosServices;
19 |
20 | public DebitosController(IMapper mapper, IDetranVerificadorDebitosService detranVerificadorDebitosServices)
21 | {
22 | _Mapper = mapper;
23 | _DetranVerificadorDebitosServices = detranVerificadorDebitosServices;
24 | }
25 |
26 | [HttpGet()]
27 | [ProducesResponseType(typeof(SuccessResultModel>), StatusCodes.Status200OK)]
28 | public async Task Get([FromQuery]VeiculoModel model)
29 | {
30 | var debitos = await _DetranVerificadorDebitosServices.ConsultarDebitos(_Mapper.Map(model));
31 |
32 | var result = new SuccessResultModel>(_Mapper.Map>(debitos));
33 |
34 | return Ok(result);
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/WebAPI/Mapper/DetranMapper.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using DesignPatternSamples.Application.DTO;
3 | using DesignPatternSamples.WebAPI.Models.Detran;
4 |
5 | namespace DesignPatternSamples.WebAPI.Mapper
6 | {
7 | public class DetranMapper : Profile
8 | {
9 | public DetranMapper()
10 | {
11 | CreateMap();
12 | CreateMap();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/WebAPI/Middlewares/ExceptionHandlingMiddleware.cs:
--------------------------------------------------------------------------------
1 | using DesignPatternSamples.WebAPI.Models;
2 | using Microsoft.AspNetCore.Http;
3 | using Microsoft.Extensions.Logging;
4 | using Newtonsoft.Json;
5 | using System;
6 | using System.Net;
7 | using System.Threading.Tasks;
8 |
9 | namespace DesignPatternSamples.WebAPI.Middlewares
10 | {
11 | public class ExceptionHandlingMiddleware : IMiddleware
12 | {
13 | private readonly ILogger _Logger;
14 |
15 | public ExceptionHandlingMiddleware(ILogger logger)
16 | {
17 | _Logger = logger;
18 | }
19 |
20 | public async Task InvokeAsync(HttpContext context, RequestDelegate next)
21 | {
22 | try
23 | {
24 | await next(context);
25 | }
26 | catch (Exception e)
27 | {
28 | _Logger.LogError(e, e.Message);
29 | await HandleExceptionAsync(context);
30 | }
31 | }
32 |
33 | private Task HandleExceptionAsync(HttpContext context)
34 | {
35 | var code = HttpStatusCode.InternalServerError;
36 |
37 | string result = JsonConvert.SerializeObject(new FailureResultModel("Ocorreu um erro inesperado"));
38 |
39 | context.Response.ContentType = "application/json";
40 | context.Response.StatusCode = (int)code;
41 |
42 | return context.Response.WriteAsync(result);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/WebAPI/Models/AbstractResultModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace DesignPatternSamples.WebAPI.Models
4 | {
5 | public abstract class AbstractResultModel : IResultModel
6 | {
7 | public TEntity Data { get; protected set; }
8 |
9 | public abstract bool HasSucceeded { get; }
10 |
11 | public IEnumerable Details { get; protected set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/WebAPI/Models/Detran/DebitoVeiculoModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace DesignPatternSamples.WebAPI.Models.Detran
4 | {
5 | public class DebitoVeiculoModel
6 | {
7 | public DateTime DataOcorrencia { get; set; }
8 | public string Descricao { get; set; }
9 | public double Valor { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/WebAPI/Models/Detran/VeiculoModel.cs:
--------------------------------------------------------------------------------
1 | namespace DesignPatternSamples.WebAPI.Models.Detran
2 | {
3 | public class VeiculoModel
4 | {
5 | public string Placa { get; set; }
6 | public string UF { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/src/WebAPI/Models/FailureResultModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace DesignPatternSamples.WebAPI.Models
4 | {
5 | public class FailureResultModel : AbstractResultModel
6 | {
7 | public override bool HasSucceeded => false;
8 |
9 | public FailureResultModel(TEntity data, IEnumerable details)
10 | {
11 | Data = data;
12 | Details = details;
13 | }
14 | }
15 |
16 | public class FailureResultModel : FailureResultModel