Skip to content

Instantly share code, notes, and snippets.

@Camilotk
Last active August 28, 2019 09:40
Show Gist options
  • Save Camilotk/12d42bfa3dc1dd113ce65a99be5f4e48 to your computer and use it in GitHub Desktop.
Save Camilotk/12d42bfa3dc1dd113ce65a99be5f4e48 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
namespace ControleDeEntregas.Models
{
public sealed class Banco<T>
{
public static bool Update(IRepository<T> repositorio, T element)
{
repositorio.Update(element);
return repositorio.Success;
}
public static bool Create(IRepository<T> repositorio, T element)
{
repositorio.Create(element);
return repositorio.Success;
}
public static IEnumerable<T> GetAll(IRepository<T> repository)
{
return repository.GetAll();
}
public static T GetByID(IRepository<T> repositorio, int id)
{
return repositorio.GetByID(id);
}
public static bool Remove(IRepository<T> repositorio, int id)
{
repositorio.Remove(id);
return repositorio.Success;
}
public static bool Remove(IRepository<T> repositorio, T element)
{
repositorio.Remove(element);
return repositorio.Success;
}
}
}
using System;
namespace ControleDeEntregas.Models
{
public partial class Pedido
{
public int ID { get; set; }
public string ClienteID { get; set; }
public Nullable<int> EmpregadoID { get; set; }
public Nullable<System.DateTime> DataPedido { get; set; }
public Nullable<System.DateTime> DataPrevisaoEntrega { get; set; }
public Nullable<System.DateTime> DataPostagem { get; set; }
public Nullable<int> MetodoEntrega { get; set; }
public Nullable<decimal> Freight { get; set; }
public string ClienteNome { get; set; }
public string ClienteEnderecoEntrega { get; set; }
public string ClienteCidadeEntrega { get; set; }
public string ClienteEstadoEntrega { get; set; }
public string ClienteCepEntrega { get; set; }
public string ClientePaisEntrega { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace ControleDeEntregas.Models
{
interface IRepository<T>
{
bool Success { get; }
void Update(T element);
void Create(T element);
IEnumerable<T> GetAll();
T GetByID(int id);
void Remove(int id);
void Remove(T element);
}
}

Visual Studio 2019

  1. Criar um novo Projeto
  • Ctrl+Shift+N
  • Arquivo -> Novo -> Projeto
  1. Selecionar 'Aplicativo do Windows Forms'
  • Dar nome da .sln de 'Teste'
  • Dar nome do Projeto de 'Controle x'
  1. Clicar com o botão direito sobre o Projeto -> Adicionar -> Nova Pasta * 3 e dar os nomes:
  • Model
  • Presenter
  • View
  1. Mover o Form1 para dentro de View e renomea-lo para 'JanelaPrincipal.cs' (fazer o mesmo com seu Construtor)
  2. Importar <nome_do_projeto>.View dentro de Program.cs
  3. Rodar e ver se tudo está funcionando

Model

  1. Criar a conexão na Model, clicar sobre Model e em Ctrl+Shift+A ou Mouse Direito -> Adicionar -> Novo Item...

  2. Criar as abstrações do que será salvo

  3. Criar a Interface 'IRepository' que vai implementar os Métodos Create, Update, Read e Delete

  4. Criar a classe <objeto_a_salvar><banco>Repository que implementa IRepository (criando uma prop DB e instanciando a Classe de BD no construtor, caso necessário).

  5. Criar um objeto sealed Banco<T> que possui métodos estáticos que recebem uma instância de IRepository (qualquer forma de persistencia) e um dado e faz as operações.

Isso! A estrutura fica:
\Models
|-\Banco
|-\IRepository
|-\Pedido
|-\PedidoDapperRepository

Se formos chamar o código no Presenter ele fica abstraído da seguinte forma:

// Instancia uma nova conexão
PedidoDapperRepository PedidosDaSemana1 = new PedidoDapperRepository();
// Faz as Querys
Banco<Pedido>.Create(PedidosDaSemana1, new Pedido() { ID = 0, ClienteID = 1.ToString(), ClientePaisEntrega = "Chile" } ); // Add
Pedido pedido1 = Banco<Pedido>.GetByID(PedidosDaSemana1, 0); // Get
Console.WriteLine(pedido1.ClientePaisEntrega); // Imprime o resultado

View

  1. Dentro de Views criar a insterface pública IView que representará o contrato das Views, ajudando a reduzir o acoplamento dos eventos

  2. Agora vamos criar uma outra interface pública I<objeto>Operations (ex: IPedidoOperations) que irá importar Models e herdar de IView e será implementada pela View que irá exibir os dados do <objeto>, a interface vai implementar uma List de <objeto> e uma série de EventHandlers que irão representar as ações na Interface com eventos que serão implementados, cada event/EventHandler fica

// Ex grupos - IEnumerable (qualquer lista percorrivel)
IEnumerable<Object> elements;
//Ex indexador
string this[string key] { get; }
// Ex event
event EventHandler<EventoAserImplemetado> acao;
  1. Criar uma pasta chamada 'Helpers' e dentro outra chamada 'Events' e ir em I<objeto>Operations importa-la e pedir pro VS gerar os eventos não implementados passando o mouse sobre os eventos sublinhados não implementados e em 'Gerar novo tipo' no caminho do novo arquivo colocar \Helpers\Events\ antes do nome do arquivo

  2. Cada Classe deve importar System e herdar de EventArgs ex - Classe de Exemplo

  3. Também deve implementar uma propriedade privada que irá guardar a informação passada entre view e presenter e uma outra publica com Get e Set que aponta para ela. Também colocar o Construtor que seta o valor Default da mesma. Ex - Classe de Exemplo

Classe de Exemplo

using System;
using ControleDeEntregas.Models;

namespace ControleDeEntregas.Events
{
    public class AddPedidoEventArgs : EventArgs
    {
        
        private Pedido novoPedido;

        AddPedidoEventArgs(Pedido pedido)
        {
            this.novoPedido = pedido;
        }
        public Pedido NovoPedido
        {
            get { return this.novoPedido; }
            set { if(value is Pedido) this.novoPedido = value; }
        }
    }
}

Presenter

  1. Na pasta Helpers criamos uma Interface INavigator que será responsável por definir a navegação entre formulários e possui o contrato com dois métodos:
  • NavigateTo(Form page)
  • NavigateTo(Form page, Dictionary<string, string> queryStringParams) // N vai ser usado agora
  1. Implementar em Helpers uma classe concreta Navigator que implementa INavigator e que o método NavigateTo retorna um

Presenters

  1. Vamos criar uma classe <objeto>OperationsPresenter em Presenters, que importa:
  • Views
  • Models
  • Helpers.Events
  • Helpers.Navigators

e que vai ter:

  • uma propriedade privada de nome 'view' do tipo I<objeto>Operations que é a interface deste objeto que a View implementa.
  • uma propriedade publica de nome 'banco' do tipo Banco
  • uma propriedade privada de nome 'repository' do tipo IRepository
  • uma propriedade privada de nome 'navigator' do tipo INavigator
  • uma propriedade publica bool de nome 'Success' que o get retorna repository.Success
  • uma propriedade publica de nome View com get e set que aponta para view, com AttachEventsToView() abaixo de set value
  1. Declaramos o Construtor dessa classe que recebe IRepository Repository e que irá receber qualquer implmentação dessa interface e guardar na propriedade repository, INavigator Navigator que recebe um novo objeto Navigator e guarda na propriedade navigator e deverá inicializar banco e a view.
  2. Vamos criar então um método AttachEventsToView ou AdicionaEventosAoView que configura os eventos da view, para isso ele irá pegar os métodos do contrato I<objeto>Operations e carregalos com métodos ainda não declarados do Presenter
private void AttachEventsToView()
{
  // O método AddPedido declarado em IPedidoOperations recebe o método AoAddPedido ainda não declarado 
  // O método AoAddPedido será declarado no Presenter, abaixo dele.
  view.AddPedido += AoAddPedido; // PT
  view.GetPedido += OnGetPedido; // EN
  // ... continua declarando todas as implementações em IPedidosOperations
}
  1. Clicamos com o direito sob os métodos não implementados -> Gerar Método...
  2. Implementamos o método chamando o Objeto Banco com o tipo genérico que estamos trabalhando e então chamamos seu método estático correspondente passando nosso repositorio e o objeto armazenado no argumento e do tipo que criamos quando extendemos os eventos em I<objeto>Operations na Pasta 'Events' e adicionamos informações extras que guardam o que está passando entre View e Presenter.
private void AoAddPedido(object sender, AddPedidoEventArgs e)
{
  Banco<Pedido>.Create(repository, e.NovoPedido);
}

private void OnGetPedido(object sender, GetPedidoEventArgs e)
{
  e.PedidoDetails = Banco<Pedido>.GetByID(repository, e.PedidoId);
}

Forms

  1. Para implementar os Forms corretamente, passamos a cada um deles a implementação da sua interface I<objeto>Operations respectiva e criamos uma propriedade do <objeto>OperationsPresenter de nome 'presenter' instanciada recebendo uma implementação concreta de IRepository e de INavigator em seu construtor.
  2. Clicamos para o VSCode gerar a implementação da interface e passamos o using do <objeto>.Presenters
  3. Instanciamos a propriedade pública View de 'presenter' com this
  4. Criamos a Interface no Designer e chamamos os EventHandlers assim para lidarem com a informação (ela será passada para o método no 'presenter' - ex: presenter.AddPedido() - que passará para AoAddPedido que vai gravar e.NovoPedido no BD

obs: e: Instancia de AddPedidoEventArgs - criada ao evento ocorrer no form que recebe o parametro do construtor (pedido) e guarda em sua propriedade e.NovoPedido

Ex de evento:

private void BtnCadastrar_Click(object sender, EventArgs e)
{
  Pedido pedido = new Pedido()
  {
    ID = int.Parse(txtID.Text),
    ClienteNome = txtNome.Text,
    ClientePaisEntrega = txtPais.Text
  };
  AddPedido(this, new AddPedidoEventArgs(pedido));
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace ControleDeEntregas.Models
{
class PedidoDapperRepository : IRepository<Pedido>
{
List<Pedido> Pedidos;
public PedidoDapperRepository() => Pedidos = new List<Pedido>();
public bool Success { set; get; }
public void Create(Pedido element)
{
Pedidos.Add(element);
}
public IEnumerable<Pedido> GetAll()
{
return Pedidos;
}
public Pedido GetByID(int id)
{
return Pedidos.Where( p => p.ID == id).Select(p => p).FirstOrDefault();
}
public void Remove(int id)
{
try
{
Pedidos.RemoveAt(id);
Success = true;
}
catch
{
Success = false;
}
}
public void Remove(Pedido element)
{
try
{
Pedidos.Remove(element);
Success = true;
}
catch
{
Success = false;
}
}
public void Update(Pedido element)
{
try
{
if(Pedidos.Contains(element))
{
Pedidos.RemoveAt(element.ID);
Pedidos.Insert(element.ID, element);
}
else
{
throw new Exception();
}
Success = true;
}
catch
{
Success = false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment