Editorial
Caro amigo, Já passamos da metade do ano de 2018, posso afirmar que é sempre uma grande satisfação ter você como parceiro
de muitos e muitos anos. Nossa revista sempre terá uma proposta fixa de disponibilizar diversos tipos de artigos, possibilitando
uma maior gama de aprendizado.
Para iniciar nossa série de artigos, o colaborador Hamden Vogel escreveu o artigo "Banco de Dados Orientado a
Objetos com Padrão Repository". Nesta primeira parte ele discutirá o molde de um projeto contemplando o padrão de
Repositório, onde fornece uma maneira de abstração para persistir os dados, retornando objetos de domínio para
representação destes dados em um objeto na camada de visão como a classe “TDBGrid". Já nosso outro colaborador mensal
Ricardo Barbosa Crivelli nos preparou o artigo “Desenvolvendo uma aplicação com Django”, o qual demonstra como criar uma
aplicação e como configurar as rotas para que o projeto Django as delegue para a aplicação. Demonstra também como alterar
as principais configurações do Django, como fuso horário, banco de dados e idioma, através do seu arquivo de configuração,
o “settings.py”. Não menos importante nosso consultor técnico Thiago Cavalheiro Montebugnoli redigiu o artigo “Linguagem
C# - Uma abordagem sobre Reflection”, explanando de uma forma simples e objetiva através de um exemplo prático esta
importante técnica de boas práticas na programação.
Desejo uma ótima leitura, um forte abraço e até o mês que vem!
Marcos César Silva
Diretor Técnico
Banco de Dados Orientado a Objetos com Padrão Repository - parte I
Sempre desenvolvi classes de conexões interagindo com a camada de visão, notadamente a classe TDBGrid,
utilizando datasources que referenciem datasets como ClientDataSets para servir de abstração para manipulação de
informações e solicitação de sua devida persistência. Até aí tudo bem, a não ser que você faça e refaça o processo
inúmeras vezes e percebe que sempre existe espaço para "reconstruir a roda"; em outras palavras se você criar vários
dataModules com um monte de datasets como queries, tables, stored procedures, "esparramados" com um monte de
componentes de pacotes tais como DBExpress, Zeos ou até mesmo BDE - vai notar no fim de tudo que se for necessário
alterar o projeto para utilizar outras camadas, módulos e componentes, adicionando consequentemente mais uma
camada de abstração para uma implementação alternativa para persistência dos seus dados - vai perceber que o custo
para esta alteração será completamente inviável, pois teria que alterar o sistema como um todo - e aí será mais fácil
fazer outro sistema do zero do que continuar esse atual. Então, não precisamos mais de preocupações. Vamos
implementar uma camada inteligente de persistência - o padrão Repositório!
Qual a finalidade de tudo isso? Vamos começar explicando o padrão Repositório primeiro. Este padrão não
acessa diretamente uma fonte de dados; este papel de criar e gerenciar estas conexões específicas pertence ao padrão
DAO - Data Access Object ("Objeto de Acesso a Dados"). Mas na nossa implementação, não haverá nenhum framework
ORM para dar suporte à esta interface abstraindo um banco de dados ou outro mecanismo externo de persistência -
todo nosso projeto vai construir tanto a camada do Repository quanto a camada do DAO - e os códigos ficarão em
arquivos distintos para não "se misturarem" (negócio e mapeamento de objetos com a fonte de dados, por exemplo).
Em suma, é como se desenvolvêssemos todo o código-fonte de um "hibernate" com um projeto que utiliza o "hibernate"
- mas na verdade é isso que vamos fazer - tudo em linguagem Delphi - mas em uma forma inicial, pelo menos nesta
primeira release - e indo evoluir aos poucos, pois vamos encapsular todo o comportamento da comunicação e resposta
da fonte de dados para com a nossa aplicação utilizando como exemplo as classes do pacote Zeos, e posteriormente
outros tipos de persistência.
O repositório utiliza um contrato básico, que é o estabelecimento de uma interface ou uma classe abstrata para
implementação de um CRUD, abstraindo esta persistência desacopladamente, acessando eles como uma coleção de
dados e por isso facilitando todo um controle da manipulação destes objetos, pois centralizando eles em uma camada
abstrata é muito mais fácil de gerenciar, podendo por exemplo trocar o banco de dados, até mesmo em execução do
projeto, e outras peculiaridades como geração de logs, exceções, transações, etc; representando um "mini-mundo" real
do projeto, tanto que retorna objetos de domínio que representam os dados do projeto.
Uma coleção no Delphi podemos pensar na classe TCollection. Na verdade para construir isso de forma
satisfatória e eficiente na nossa aplicação teremos que utilizar nossas classes descendendo de TCollectionItem; uma
classe genérica que descenderá de TCollection para se conectar a este TCollectionItem dito anteriormente e uma outra
classe genérica que fará o "meio de campo" entre as classes TDataSet e TCollection.
Vamos iniciar com um projeto de ocorrências. Será para ilustração dos nossos entendimentos; e será uma tabela
homônima com dois atributos - data e descrição de ocorrências - e vamos observar como a construção e conexão com
o padrão repositório será realizada:
1. Classe TOcorrencia -> TCollectionItem;
2. Classe TOcorrenciaCollection -> TCollection; 3. Classe TCollectionDataSet -> TCollection + TDataSet (permite visualizar a classe TOcorrencia citada no
item 1.
Implementamos em um banco free, o PostGres, adotado como o "pontapé inicial" da nossa construção,
e depois evoluindo para outros tipos de persistência.
Segue o modelo (script) abaixo:
CREATE TABLE hvogel.TB001_OCORRENCIA
(
NU_OCORRENCIA INTEGER NOT NULL,
NO_OCORRENCIA TEXT NULL,
DT_CADASTRO DATE NULL,
UNIQUE (NU_OCORRENCIA)
);
O repositório pertence ao modelo de um software, e ele complementa este modelo solicitando detalhes de
infra-estrutura de objetos DAO para execução de persistência - em outras palavras o repositório "não conhece" o
funcionamento de gravação de dados, nem recuperação de dados, nem remoção de dados, etc; ele apenas solicita estas
informações ao "setor responsável" e adquire elas por meio deste "setor responsável" - adquire essas informações "já
prontas e disponíveis" - mas ele não sabe como elas vieram, nem de onde elas vieram - apenas vai utilizar elas e pronto.
E depois de manusear elas, ele as "devolve" para o "setor responsável" novamente, de onde se encarregará de entregar
estas informações para a sua "casa" de forma segura e eficiente. Parece soar estranho; é como se convivesse diariamente
com estas informações, mas não sabe de nada delas. Mas é assim que funciona. E é melhor assim, pois delegando
responsabilidades o processo não se torna oneroso e custoso - pois seriam inúmeras linhas de código-fonte para
implementar um mecanismo que não lhe diz respeito - e isso poderia ser fatal para o projeto.
O repositório utiliza classes de domínio, que são as classes que representam suas tabelas - por exemplo, a
tabela acima de ocorrências - então vamos ter uma classe de domínio chamada de TOcorrencia onde os seus métodos
vão retornar este objeto de TOcorrencia como objetos de domínio do negócio. Se fosse em Java, poderíamos adotar o
seguinte exemplo demonstrado abaixo:
class OcorrenciaRepository
{
public List <Ocorrencia> OcorrenciasAprovadas();
public List <Ocorrencia> OcorrenciasReprovadas();
public List <Ocorrencia> TodasOcorrencias();
}
Mas como não é em Java, vamos imaginar como faríamos em Delphi, então pensaríamos como uma
classe descendente de TCollection, como mencionado anteriormente.
TOcorrenciaCollection = class (TCollection)
private
function GetItem(Index: Integer): TOcorrencia;>
procedure SetItem(Index: Integer; AObject: TOcorrencia);
//function Remove(AObject: THTTPFile): Integer;
public
function Add: TOcorrencia;
function AddEx(DataOcorrencia : string; DescOcorrencia: string):
TOcorrencia;
property Item[Index: Integer]: TOcorrencia read GetItem;
Repare na última linha destacada em negrito - ela retorna um objeto de TOcorrencia, e este método
published juntamente com a outra linha destacada em negrito mais acima - a function GetItem, representando o
getter desta propriedade representa uma lista de coleções de objetos de ocorrências! Algo como a classe List do Java
também já mencionado mais acima.
function TOcorrenciaCollection.GetItem(Index: Integer): TOcorrencia;
begin
Result := inherited Items[Index] as TOcorrencia;
end;
procedure TOcorrenciaCollection.SetItem(Index: Integer; AObject: TOcorrencia);
begin
inherited Items[Index] := AObject;
end;
Desta forma, bastaríamos um loop da propriedade de Items (exemplo: "for i := 0 to Items.Count-1 do" )
para reproduzir o efeito de percorrer as instâncias desta lista de objetos da coleção, e obter a recuperação dos
objetos desejados.
Então, para iniciar de forma correta é importante termos em mente outras considerações:
1. A classe deve utilizar a diretiva de compilação {$M+}, que tem o objetivo de habilitar o controle de geração
da RTTI (RunTime Type Information) para com ela. Isso é importante pois vamos utilizar os atributos da sua tabela como
os métodos published da sua classe de domínio;
2. A classe também deve herdar da classe da VCL TCollectionItem ou alguma descendente dela, para que possa
servir de base para uma classe de coleção respectiva (TCollection ou descendente dela), seja por base dela mesma ou
uma genérica. Vamos evoluir no segundo artigo para a segunda opção, por gerenciar como um metadado esta
abordagem de coleções destes objetos.
3. A classe de coleção não sabe nem conhece a classe do banco de dados - ela chama a classe do repositório,
que por sua vez solicitará a classe do DAO a requisição desejada.
Segue abaixo um exemplo de código-fonte para ilustrar o "esqueleto" do nosso framework:
type
IConnection = interface
['{34AD82AA-1D2F-464A-AB91-F02EB5A8AE2B}']
procedure Close;
function Execute(const fObjectName: string): TDataSet;
function RunPersistenceCommand(const fCommand: string):
Boolean; end;
type
TXCollectionItemClass = class of TXCollectionItem;
protected
procedure SingletonError;
public
destructor Destroy; override;
end;
type
TOcorrencia = class (TXCollectionItem, IConnection)
private
FDataOcorrencia: string;
FDescOcorrencia: string;
FRefCount: Integer;
published
property DataOcorrencia: string read FDataOcorrencia write FDataOcorrencia;
property DescOcorrencia: string read FDescOcorrencia write FDescOcorrencia;
public
constructor Create;
procedure Close;
function Execute(const fObjectName: string): TDataSet;
function RunPersistenceCommand(const fCommand: string): Boolean;
procedure SingletonError;
destructor Destroy; override;
protected
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
TOcorrenciaCollection = class (TCollection)
private
function GetItem(Index: Integer): TOcorrencia;
procedure SetItem(Index: Integer; AObject: TOcorrencia);
public
function Add: TOcorrencia;
function AddEx(DataOcorrencia : string; DescOcorrencia: string): TOcorrencia;
property Item[Index: Integer]: TOcorrencia read GetItem;
procedure Delete(Index: Integer);
end;
Conclusão
Pudemos ver nesta primeira parte uma breve explanação do nosso projeto, que é um projeto de
ocorrências, implementando o padrão Repository com persistência (inicial) no BD PostGres; vimos como
empregar as classes de coleções (TCollection e TCollectionItem) para servir de base para nossas classes de
domínio e consequentemente abstrair de forma orientada a objetos o gerenciamento desta classe na camada
de visão, tendo como suporte o controle DBGrid porque é um dos mais completos para visualização de um
DataSet de forma dinâmica; no nosso caso o DataSet dinâmico vai ser o próprio objeto da coleção já
transformado em um "banco de dados" orientado a objeto - visto que nenhum acesso ou solicitação de acesso
ao banco de dados será realizado por este objeto - quem fará portanto este acesso será a camada de repositório. Iremos no próximo artigo evoluir esta implementação, utilizando RTTI para "descobrir" em tempo de
execução qual a classe que terá sua coleção a ser utilizada em controles da VCL de DataSets, como DBGrid e
demais classes (como DBNavigator, DBEdit, etc) - portanto, bons estudos, boa leitura, e boas idéias! Até a
próxima!
Sobre o Autor
Hamden Vogel, Consultor TheClub
E-mail: [email protected]
Desenvolvendo uma aplicação com Django
Introdução
Continuando a nossa serie sobre Django e Python, vamos aprender a criar uma aplicação e como alterar as configurações no arquivo settings.py. Aprenderemos também a configurar as rotas para que estas sejam
delegas à aplicação. Espero muito que gostem da leitura e se divirtam com essa linguagem que é incrivelmente
versátil.
Ativando o ambiente virtual (virtualenv)
Como nós iremos precisar das mesmas bibliotecas que utilizamos no artigo anterior, vamos ativá-lo para que
não seja necessária a instalação. Para isso abra o console e digite o comando:
workon nome_do_ambiente
O ambiente no artigo anterior se chama the_club_django,então o comando ficaria:
workon the_club_django
Criando a aplicação
Para iniciarmos vamos navegar pelo terminal até a pasta que contém o esqueleto criado no artigo anterior e
digitar o seguinte comando se você estiver no Linux ou no macOS X:
python3 manage.py startapp biblioteca
No Windows o comando deverá ser:
py -3 manage.py startapp biblioteca
Note que o diretório biblioteca foi criado e sua estrutura é:
meusite/
manage.py
biblioteca/
migrations/
admin.py h
apps.py
models.py k
tests.py
views.py
__init__.py
Note que nós temos a pasta migrations, ela é a responsável por atualizar automaticamente o banco de
dados quando você alterar os seus modelos. O arquivo __init__.py, apesar de vazio server para que o Django reconheça o diretório como um
pacote Python (mais conhecido como Python Package) e permite que você o utilize como parte de outro projeto.
Registrando a aplicação
Para que as ferramentas e bibliotecas sejam carregadas ao executar a aplicação é necessário registrá-la. Para isso devemos adicionar ao final da lista INSTALLED_APPS a linha em destaque.
Abra as configurações do projeto em meusite/meusite/settings.py e procure pela lista INSTALLED_APPS e adicione uma linha ao final conforme o código abaixo.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'meusite.apps.biblioteca',
]
Esta nova linha especifica a classe BibliotecaConfig que foi gerada automaticamente e está armazenada no
arquivo /meusite/biblioteca/apps.py.
Se você notou que já existem várias outras aplicações instaladas e também muitos outros middlewares, não
se assuste, nem remova estas linhas. Elas são responsáveis por gerar e assegurar o suporte à área de administração
do site do Django.
Configurando o banco de dados
Como não esperamos um grande volume de acessos à nossa aplicação, nós iremos utilizar o SQLite como
exemplo, mas se você desejar adicionar outro sistema gerenciador de banco de dados (SGBD) ou até mesmo alterar as configurações do SQLite, basta alterar a lista DATABASES do arquivo settings.py.
A comunidade defende que você deve tentar manter o mesmo SGBD nos ambientes de produção e
desenvolvimento para que você minimize os conflitos que podem ser causados pela mudança de plataforma.
Se você preferir mudar o nome do arquivo gerado, basta alterar o trecho em destaque:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Alterando as configurações de hora
Existem muitas configurações que podem ser alteradas no arquivo settings.py e uma delas é o fuso horário.
Para nos certificarmos que as configurações estão corretas vamos alterar a propriedade TIME_ZONE:
TIME_ZONE = 'America/Sao_Paulo'
Se você está em outra região basta consultar a lista de timezones na Wikipédia em
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
Alterando o modo de DEBUG
O modo de debug ou de depuração, para quem não sabe, é o modo em que os erros são mostrados de forma
mais detalhada do que somente o código HTTP. Ele deve ser sempre False em produção, mas nesse caso vamos deixa-
lo como True.
DEBUG = True
Traduzindo a aplicação
A última configuração que iremos alterar no arquivo de configuração é a que diz respeito ao idioma das
mensagens que são geradas automaticamente. Altere a propriedade LANGUAGE_CODE para o português do Brasil
alterando o código para:
LANGUAGE_CODE = 'pt-br'
Configurando as rotas
Um ponto que muita gente se perde no django é em relação às rotas, pois se você verificar o arquivo urls.py
está localizado na pasta do projeto (meusite/meusite/urls.py) e não da aplicação. Você pode utilizar este
arquivo para definir suas rotas, mas é mais usual delegar esta função para a aplicação. Os mapeamentos são feitos através da variável urlpatterns que é uma lista de funções path(). Cada
path() está associada à uma view específica, que será exibida caso o endereço corresponda a alguma regra. Note que inicialmente a urlpatterns define que toda URL que contenha admin/ será mapeada para o modulo admin.sites.url que contém as regras e mapeamentos para a área administrativa do site.
O arquivo contém também as instruções de como mapear uma URL:
"""meusite URL Configuration
The `urlpatterns` list routes URLs to views. For more
information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
Add an import: from my_app import views
Add a URL to urlpatterns: path('', views.home,
name='home') Class-based views
Add an import: from other_app.views import Home
Add a URL to urlpatterns: path('', Home.as_view(),
name='home')
Including another URLconf
Import the include() function: from django.urls import
include, path
2. Add a URL to urlpatterns: path('blog/',
include('blog.urls'))
"""
Adicione o código abaixo para que qualquer URL com o prefixo biblioteca/ seja enviado para o módulo
biblioteca.urls que será armazenado no arquivo biblioteca/urls.py. As alterações e inclusões
estão em negrito.
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('biblioteca/', include('biblioteca.urls')),
]
Redirecionando a URL raiz
Como nós só teremos a biblioteca em nosso projeto (pelo menos até agora), seria interessante redirecionar quem acessar a URL raiz (a 127.0.0.1:8000, por exemplo) para o endereço da biblioteca. Adicione o código em
negrito para o arquivo urls.py:
...
from django.conf.urls import include
from django.views.generic import RedirectView
urlpatterns = [
path('admin/', admin.site.urls),
path('biblioteca/', include('biblioteca.urls')),
path('', RedirectView.as_view(url='/biblioteca/')),
]
Servindo arquivos CSS e JavaScript
O Django por padrão não serve arquivos estáticos como CSS, JavaScript e imagens, mas sabemos que isso é de
extrema importância no desenvolvimento de nossa aplicação. A solução é bastante simples, basta adicionar o código
abaixo para que o servidor forneça os arquivos estáticos quando requisitados:
...
from django.views.generic import RedirectView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('biblioteca/', include('biblioteca.urls')),
path('', RedirectView.as_view(url='/biblioteca/')),
]
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT);
Você notou que nós concatenamos a função static à urlpatterns? O Python é tão versátil que isso pode ser
feito inline se você preferir:
urlpatterns = [
path('admin/', admin.site.urls),
path('biblioteca/', include('biblioteca.urls')),
path('', RedirectView.as_view(url='/biblioteca/')),
] + static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT);
Testando
Vamos executar o servidor para testar a nossa aplicação através do comando:
python3 manage.py runserver
Ou se você estiver no Windows:
py -3 manage.py runserver
Agora acesse a URL http://127.0.0.1:8000 e veja que o resultado é uma página de erro 404. Ela
indica que a página não pode ser encontrada, ou seja, nossa aplicação está funcionando como deveria já que nós
ainda não criamos nenhuma página! Esse será o próximo passo que veremos no artigo do mês que vem!
Conclusão
No artigo de hoje aprendemos a criar uma nova aplicação em um projeto Django e como configuramos as rotas
para que possamos iniciar o desenvolvimento das views. Aprendemos também um pouco sobre um dos arquivos mais
importantes do Django, o settings.py, responsável por armazenar todas as configurações do projeto.
Sobre o Autor
Ricardo Barbosa Crivelli, mais conhecido como Rico Crivelli, é formado como Bacharel em Sistemas de Informação e Licenciado em Computação pela Universidade Estadual do Norte do Paraná e pós-graduando em Informática na Educação. Atualmente é Técnico em TI no Instituto Federal de São Paulo –
Câmpus Avaré. Tem como especialidade a linguagem PHP e o framework Symfony, apesar de adorar trabalhar com front-end e desenvolvimento mobile. Possuir as certificações COBiT 4.1 Foundation e Delphi 2006
Developer. E-mail para contato: [email protected]
E-mail: [email protected]
Linguagem C# - Uma abordagem sobre Reflection
Caro amigo leitor,
Neste mês entrarei em um assunto muito importante existente em praticamente todas as linguagens de programação, “Reflection”, que traduzindo para o português significa “Reflexão”. Para quem nunca ouviu falar, em
poucas palavras com a reflexão podemos escrever o código possibilitando realizar uma leitura dos metadados dos
objetos em tempo de execução, contendo informações das estruturas existentes nas classes. Entende-se como estruturas
os métodos e atributos.
Uma característica também importante da reflexão é a possibilidade de um programa modificar a estrutura e o
seu comportamento interno. Na arquitetura .NET a reflexão fornece objetos do tipo “Type”, os quais descrevem os
assemblies, módulos ou tipos.
Ao utilizarmos a reflexão estamos tornando o código mais robusto e adepto às denominadas boas práticas de
programação.
Para este artigo usaremos a linguagem C# junto com um projeto “Windows Forms”. A princípio criaremos algumas classes de exemplo para em seguida efetuarmos a inserção de dados e a leitura através de um método
específico da arquitetura .NET. Desenvolveremos também um exemplo básico para demonstrar todo o funcionamento da técnica “Reflection”.
Principais Métodos e Propriedades
Classe object: Este construtor é chamado pelos construtores em classes derivadas, mas ele também pode ser
usado para criar uma instância da classe “object”. Método GetType(): Este método pode ser usado para retornar “Type” de objetos que representam todos
os tipos do .NET Framework.
Podemos destacar algumas principais categorias, sendo:
- Classes, que são derivados de “System.Object”;
- Valor de tipos que derivam de “System.ValueType”;
- Interfaces, que são derivados de “System.Object” começando com o .NET Framework 2.0;
- Enumerações, que são derivadas de “System.Enum”;
- Delegados, que são derivados de “System.MulticastDelegate”.
Propriedade Name: Retorna o “Name” da propriedade através da classe “Type”.
Método GetProperties(): Obtém um vetor de todas as propriedades do objeto.
Método GetValue(object): Obtém o valor da instância.
Criando o layout do exemplo
Nosso layout será composto por um “Button” o qual irá disparar a codificação principal e um “ListBox”, o qual
irá armazenar todos os valores. Para isto abra o Microsoft Visual Studio 2017 clicando em “Arquivo/Novo/Projeto”
escolhendo a opção “Aplicativo do Windows Forms”. Ver Figura 01.
Figura 01: Criando o projeto.
Abaixo teremos uma ideia geral do layout proposto. Ver Figura 02.
Figura 02: Layout.
Codificando o exemplo
Para realizarmos a leitura dos métodos através da técnica “Reflection” implementaremos algumas
classes contendo alguns atributos, como por exemplo: “Socio”, “Plano”, “Venda” e “ItemVenda”.
Atenção: Deveremos ter em mente que estas classes são apenas para fins didáticos.
Classes utilizadas
public class Socio {
public int IdSocio { get; set; }
public string Nome { get; set; }
public string Documento { get; set; }
public string Endereco { get; set; }
}
public class Plano {
public int IdPlano { get; set; }
public string Descricao { get; set; }
public Decimal Valor { get; set; }
}
public class Venda {
public int IdVenda { get; set; } public int IdSocio { get; set;
public DateTime DataVenda { get; set; }
public Decimal Total { get; set; } }
public class ItemVenda
{
public int IdItemVenda { get; set; }
public int IdVenda { get; set; }
public int IdPlano { get; set; }
}
Listagem 01: Classes de exemplo.
A próxima etapa será a de desenvolver um método responsável por ler automaticamente todos os dados das
classes supracitadas. Ver Listagem 02.
private void DadosReflection (object obj) {
var tipo = obj.GetType();
lst.Items.Add ("Classe " + tipo.Name);
foreach (var prop in tipo.GetProperties())
{ Documento = ": " + prop.GetValue(obj));
}
lst.Items.Add ();
}
Listagem 02.
O método genérico “DadosReflection” será do tipo “void”, ou seja, não retornará nenhum tipo de dado. Terá
apenas um parâmetro de entrada do tipo “object” (Neste momento inserimos a classe desejada como parâmetro). Iremos
obter o tipo do objeto através do método “GetType()”. Faremos um laço para percorrer todos os atributos da classe
informando o nome e valor respectivamente pelas propriedades “Name” e “GetValue”. Não podemos esquecer de
adicioná-los ao listbox.
No botão “Executar Reflection” iremos alimentar as classes e executar o método “DadosReflection”. Podemos
conferir todos os detalhes através da listagem 03.
private void btnExecutar_Click (object sender, EventArgs e)
{ var socio = new Socio()
{
IdSocio = 1, Documento = "123.123.123-12", Nome = "Thiago Cavalheiro Montebugnoli", Endereco = "Rua The Club, 123456"
};
var plano = new Plano()
{ IdPlano = 44, Descricao = "Profissional C#", Valor = Decimal.Parse("100,00")
};
var venda = new Venda()
{
IdVenda = 2, IdSocio = 1, DataVenda = DateTime.Now,
Total = Decimal.Parse ("150,00") };
var itemvenda = new ItemVenda()
{ IdItemVenda = 1, IdVenda = 2,
IdPlano = 44, };
DadosReflection(socio);
DadosReflection(plano); DadosReflection(venda); DadosReflection(itemvenda);
};
Listagem 03.
Invocaremos o mesmo método “DadosReflection” para todas as classes implementadas. Importante salientar que
o construtor “object” é o responsável por englobar todos os tipos de classes criadas pelo usuário. Teremos o resultado de
nosso exemplo na Imagem 03.
Figura 03: Projeto em run-time.
Conclusão
A ideia de reaproveitamento de códigos pode ser considerada um dos pilares das boas práticas de programação.
Quando trabalhamos com “Reflexão”, mais conhecida como “Reflection”, conseguimos aumentar a robustez de nossos
sistemas com um reaproveitamento intensivo de códigos. A proposta deste artigo foi o de abordar de uma forma mais
simples possível o uso desta prática, podendo ser implementada em situações de proporcionalidade maior.
Vou ficando por aqui, um grande abraço!
Referências
https://msdn.microsoft.com/pt-br/library/system.object.object(v=vs.110).aspx
https://msdn.microsoft.com/pt-br/library/system.reflection.memberinfo.name(v=vs.110).aspx
Sobre o Autor
Thiago Cavalheiro Montebugnoli adora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de Botucatu – SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Como
experiências profissionais mais recentes, possui em seu currículo sua atuação no Centro de Processamento de Dados da Prefeitura Municipal de
Itaí-SP e atualmente compõe a equipe da Coordenadoria Tecnologia da Informação no IFSP – Instituto Federal do Estado de São Paulo em Avaré.
Além disso, é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft
Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft
Certified Solution Developer.
E-mail: [email protected]