- Criar um novo Projeto
- Ctrl+Shift+N
- Arquivo -> Novo -> Projeto
- Selecionar 'Aplicativo do Windows Forms'
- Dar nome da .sln de 'Teste'
- Dar nome do Projeto de 'Controle x'
- Clicar com o botão direito sobre o Projeto -> Adicionar -> Nova Pasta * 3 e dar os nomes:
- Model
- Presenter
- View
- Mover o Form1 para dentro de View e renomea-lo para 'JanelaPrincipal.cs' (fazer o mesmo com seu Construtor)
- Importar <nome_do_projeto>.View dentro de Program.cs
- Rodar e ver se tudo está funcionando
-
Criar a conexão na Model, clicar sobre Model e em Ctrl+Shift+A ou Mouse Direito -> Adicionar -> Novo Item...
-
Criar as abstrações do que será salvo
-
Criar a Interface 'IRepository' que vai implementar os Métodos Create, Update, Read e Delete
-
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).
-
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
-
Dentro de Views criar a insterface pública IView que representará o contrato das Views, ajudando a reduzir o acoplamento dos eventos
-
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;
-
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
-
Cada Classe deve importar System e herdar de EventArgs ex - Classe de Exemplo
-
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; }
}
}
}
- 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
- Implementar em Helpers uma classe concreta Navigator que implementa INavigator e que o método NavigateTo retorna um
Presenters
- 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
- 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.
- 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
}
- Clicamos com o direito sob os métodos não implementados -> Gerar Método...
- 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);
}
- 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.
- Clicamos para o VSCode gerar a implementação da interface e passamos o using do <objeto>.Presenters
- Instanciamos a propriedade pública View de 'presenter' com this
- 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));
}