Apaixonado por tecnologia. Trabalho com tecnologia desde 2003.

Saiba mais sobre minha vida profissional aqui .

Fale comigo.
Siga-me no Twitter
Ultimos comentários
Calendário de Posts
<<  novembro 2017  >>
stqqssd
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Siga o @DicaDoNerd no Twitter e acompanhe as novidades


Eu gosto muito de soluções genéricas e por isso abuso do tipo <T>. Para quem não conhece T é um tipo genérico, pois, hoje quando criamos um método precisamos informar qual é o tipo do parâmetro, por exemplo:

public void Teste(string Parametro)

 

Neste caso, o tipo é String. Agora, imagine que você precise criar uma solução genérica. Um impressor de dados por exemplo. Você trabalha com 20 entidades no seu projeto, para cada classe você precisaria sobrescrever o método ToString(). Seria um trabalhão certo? ERRADO!

Seguindo este modelo, vamos criar duas classes: Cliente e Fornecedor:

    public class Cliente
    {
        public int IDCliente { get; set; }
        public string NomeCliente { get; set; }
        public DateTime DataNascimento { get; set; }
    }
 
    public class Fornecedor
    {
        public int IDFornecedor { get; set; }
        public int NomeFornecedor { get; set; }
    
    }

Classes criadas, agora vamos criar uma nova classe chamada Impressao que será responsável por receber qualquer entidade e gerar uma string com o nome e valor de cada propriedade.

É necessário importar o namespace System.Reflection;

using System.Reflection;

Você deve observar que informamos o <T> antes da passagem do parâmetro, esta é a forma que o compilador entende que T será um tipo e assim podemos acessá-lo.

Exibição da Imagem com a Exibição do T como escolha do Tipo no parâmetro

Agora, vamos contruir a classe que será responsável pela impressão das entidades.

    public class Impressao
    {
 
        public string Imprimir<T>(T Entidade) 
        {
            //"Pegamos" o tipo de T, para termos acessos as propriedades e valores.
            Type tipoEntidade = typeof(T);
 
            //Pegamos as propriedades da entidade.
            PropertyInfo[] propriedades = tipoEntidade.GetProperties(); 
 
            StringBuilder sb = new StringBuilder();
            object ValorDaPropriedade = null;
            
            //Passo por todas as propriedades
            foreach (PropertyInfo propriedade in propriedades)
            {
                //Pego o valor da propriedade. 
                ValorDaPropriedade = propriedade.GetValue(Entidade, null);
 
                //Verifico se o valor é nulo, caso positivo, "imprimiremos NULL"
                ValorDaPropriedade = ValorDaPropriedade == null ? "NULL" : ValorDaPropriedade;
                sb.Append(String.Format("Nome da Propriedade {0} - Valor: {1} {2}",
                    propriedade.Name, ValorDaPropriedade, Environment.NewLine));
            }
 
            //Retorno a String 
            return sb.ToString();
        }

Temos as entidades e o método de impressão genérico, vamos então sobrescrever o método ToString(), nas duas classes faremos o seguinte:

public override string ToString()
{
       Impressao impressao = new Impressao();
       return impressao.Imprimir(this);
}

Feito isto, agora vamos criar a classe de teste:

    class Program
    {
        static void Main(string[] args)
        {
            Cliente cliente = new Cliente();
            cliente.DataNascimento = DateTime.Today;
            cliente.IDCliente = 1;
            cliente.NomeCliente = "Alexandre Minato";
 
            Console.WriteLine(cliente.ToString());
            Console.ReadKey();
        }
    }

E o resultado final fica assim:

Resultado Final: Impressão do Console.Writer com os nomes e valores das propriedades

Você pode baixar o exemplo completo clicando aqui: (Visual Studio 2010 – Framework 3.5).

Ícone de acessibilidade

A importância do preenchimento da propriedade alt nas imagens:
A partir de hoje, em todos os meus post’s vou fazer o possível para que haja acessibilidade. Tenho um colega de trabalho (Alexandre Teixera, vulgo Nano) que é programador com deficiência visual e ele sempre reclama da falta de acessibilidade. Vamos compartilhar conhecimento com TODOS.

Neste post, todas as imagens tem a propriedade alt preenchida, pois, assim, o software que lê as imagens, pode informar ao deficiente visual o que significa a imagem ou pelo menos uma breve descrição.

 

Até a próxima: 8-)

 

Minato

Bom, comptei um Netbook recentemente e iniciei os procedimentos para instalação dos softwares que mais utilizo no Sistema Operacional Windows 7 Starter. Instalei o Office 2010, Visual Studio 2010, como na instalação o Visual Studio já cria uma instancia default do SQL Server 2008 Express (SQLExpress), então, pensei: Após a instalação basta eu instalar o Management Studio 2008 e pronto! Cool 

Mas não foi bem isso o que aconteceu. A primeira coisa foi o aviso de incompatibilidade.

Program Compatibility Assistant

This program has known compatibility issues
fter SQL Server Setup completes, you must apply SQL Server 2008 Service Pack 1 (SP1) or a later service pack before you run SQL Server 2008 on this version of Windows.
 Mensagem de Incompatibilidade do MS 2008

 

Bom, não entendi, pois, estava com a ultima versão de todas as aplicações (Windows 7, SQL 2008, Visual Studio 2010), mas, como a opção "Check for solution online" não ajudou em nada, continuei executando a instalação do programa.

Então tive outra surpresa com a seguinte Mensagem: "Invoke or BeginInvoke cannot be called on a control until the window handle has been created".

 Mensagem de Erro ao instalar SQL MMS 2008

Passei horas tentando entender o que estava acontecendo, até que na KB da Microsoft eu vi que um pré-requisito era o Framework 3.5 instalado, então pensei: Eu tenho o Framework 4.0 instalado. Será que é isso? Por incrível que pareça, instalei o framework 3.5 e pronto. Tudo resolvido.

Eu li em alguns artigos que você poderia reinstalar o SQLServer que funcionaria também. Como no meu caso a instalação do Framework 3.5 resolveu e infelizmente não vi em nenhum site isso, resolvi postar essa dica.

 Mande suas sugestões para: contato@alexandreminato.com.br

Até a próxima 8-)

Minato

Um Grande problema que temos é o trabalho de ficar criando grid com funcionalidades CRUD (Create, Reade, Update e Delete), com este componente e algumas adaptações fica tudo mais fácil.

Um modelo de uma grid personalizada. Notem que na coluna “Descrição” há um marcador vermelho, isto está indicando que foi realizada uma alteração que ainda não foi salva (o mais fantástico é que basta um duplo clique na coluna que ela fica habilitada para edição).

A coluna vencimento é do tipo Data, assim, é possível exibir o DatePicker de uma forma muito simples. Para cada coluna há um “editor. Notem que tudo pode ser configurado (no meu site todas as mensagens estão em portugues, mas, é possível configurar para que recupere a linguagem do cliente e com trabalho mínimo, exibir mensagens em Inglês, Português ou qualquer outro idioma.

Tela de Apresentação da Grid.

Vou colocar o conteúdo HTML necessário para gerar as colunas e editores e alguns itens interessantes, como, Regex para limitar caracteres, agrupadores, enfim, muita coisa bacana, para quem quiser trocar informações, entrem em contato através do email:contato@alexandreminato.com.br

<ColumnModel ID="colModel" runat="server">

<Columns>

<ext:Column ColumnID="IDLancamento" DataIndex="IDLancamento" Header="ID" Width="25" Sortable="true" Hidden="true" />

<ext:Column DataIndex="Vencimento" Header="Vencimento" Width="100" Align="Center" Sortable="true">

<Editor>

<ext:DateField ID="txtVencimento" runat="server" Sortable="true" />

</Editor>

<Renderer Fn="Ext.util.Format.dateRenderer('d/m/Y')" />

</ext:Column>

<ext:Column DataIndex="Descricao" Header="Descricao" Width="210" Sortable="true">

<Editor>

<ext:TextField ID="txtDesc" runat="server" />

</Editor>

</ext:Column>





<ext:GroupingSummaryColumn

ColumnID="Valor"

Header="Valor"

Sortable="true"

DataIndex="ValorPrevisto"

Hideable="false"

SummaryType="Sum">

<Renderer Fn="FormataCor" />

<SummaryRenderer Fn="FormataCor" />

<Editor>

<ext:TextField ID="TextField2" runat="server" MaskRe="/[0-9\,]/" DataIndex="ValorPrevisto" />

</Editor>

</ext:GroupingSummaryColumn>

<ext:CommandColumn ColumnID="Quitar" Width="40" Header="Quitar">

<Commands>

<ext:GridCommand Icon="Accept" CommandName="Quitar" />

</Commands>

</ext:CommandColumn>

</Columns>

</ColumnModel>

Conheçam um dos melhores componentes OpenSource. www.coolite.com

Até a próxima 8-)

Minato

Estou trabalhando em um projeto pessoal em parceria com um amigo para fazer o portal administrativo do site www.baladacerta.com.br, surgiu a necessidade de criarmos log de alterações do usuário. A idéia era logarmos as alterações dos clientes em um campo do tipo XML do SQLServer 2005.

Como estou desenvolvendo com LinqToSql e com conceitos de OO, pensei em como poderia fazer a geração do Log dinamicamente. Vai aí uma dica para quem gosta de soluções automatizadas.

Para garantir que as entidades que serão comparadas são do mesmo tipo, garanto no WHERE do próprio método (where T : Y), utilizando Reflection para gerar os elementos e atributos do XML (XElement)

Ficou bem dinâmico e reutilizável.

public enum Modulo
{
Casas,
CasasDetalhes,
Financeiro,
Parceiros,
}


public XElement GravarAlteracoes<T , Y >( T EntidadeAnterior, Y NovaEntidade, Modulo modulo ) where T : Y
{

XElement xml = new XElement(modulo.ToString()); // Crio o elemente referente ao módulo

//Pego as propriedades de uma das entidades (já que as duas são iguais).
PropertyInfo [] propriedades = EntidadeAnterior.GetType().GetProperties();
//Variável que armazena o valor das propriedades
object valorAntigo, valorNovo;

//passo por todas as propriedades da entidade
foreach (PropertyInfo propriedade in propriedades)
{
//Atribuo valor as entidades.
valorAntigo = propriedade.GetValue(EntidadeAnterior, null);
valorNovo = propriedade.GetValue(NovaEntidade, null);

//Se for Null, gravo o Literal NULL
valorAntigo = valorAntigo == null ? "NULL" : valorAntigo;
valorNovo = valorNovo == null ? "NULL" : valorNovo;

//Verifico se os valores são diferentes
if (!valorAntigo.Equals(valorNovo))
{
xml.Add(new XElement(propriedade.Name, // Crio um elemento com o nome da propriedade
new XAttribute("ValorAnterior", valorAntigo), // um atributo com o valor antigo
new XAttribute("ValorAtual", valorNovo))); // um atributo com o novo valor.
}

}

return xml;
}

Para utilizar você poderia fazer assim:

XElement xml = Log.GravarAlteracoes<CasaEntidade, CasaEntidade>(entCasaBanco, entCasaTela, Log.Modulo.Casas);

O interessante é que conseguimos garantir que as duas entidades são do mesmo tipo.

Simples não é mesmo?

 

Minato.

Minato , Criado em 05/06/2010, 08:57

Durante muito tempo fiz aquelas funções mirabolantes para validação, recuperar apenas números, apenas textos e etc. Com a compreensão do Regex, estas tarefas foram sendo facilitadas, vou iniciar uma série de informações sobre Regex (Regular-Expression). Vamos utilizar a biblioteca “Microsoft VBScript Regular Expression 5.5” que está em “c:\Windows\system32\vbscript.dll”.

Vamos iniciar selecionando a referência no projeto:

referencia_vbscript

Ao incluir a referência, conseguimos acessar as classes, RegExp, Match, MatchCollection e etc.

Agora vamos imagina que queremos, em uma expressão (String) recuperar somente os caracteres numéricos. Bastaria indicarmos que queremos apenas números para o pattern do Regex. Vamos ver na prática como funciona.

Option Compare Database
Option Explicit



Public Sub Testar()

MsgBox (SomenteNumeros("Alexandre Minato 123----++adasjdlak"))

End Sub



Public Function SomenteNumeros(Expressao As String) As Integer

Dim regex As RegExp
Dim encontrados As MatchCollection

Set regex = New RegExp
regex.Global = True 'Indico que as configurações servirão para todos os métodos da classe
regex.IgnoreCase = True 'Ignoro Case Sensitive
regex.Pattern = "[0-9]" 'Indico que quero apenas números de "0 até 9"

Set encontrados = regex.Execute(Expressao) 'seto a instancia da classe com a execução do Regex

Dim strRetorno As String
Dim encontrado As Match

For Each encontrado In encontrados

'Concateno a string com o resultado
strRetorno = strRetorno + encontrado.Value
Next

SomenteNumeros = CInt(strRetorno)

End Function

SomenteNumeros("Alexandre Minato 123----++adasjdlak"))

End Sub

Public Function SomenteNumeros(Expressao As String) As Integer

Dim regex As RegExp
Dim encontrados As MatchCollection

Set regex = New RegExp
regex.Global = True 'Indico que as configurações servirão para todos os métodos da classe
regex.IgnoreCase = True 'Ignoro Case Sensitive
regex.Pattern = "[0-9]" 'Indico que quero apenas números de "0 até 9"

Set encontrados = regex.Execute(Expressao) 'seto a instancia da classe com a execução do Regex

Dim strRetorno As String
Dim encontrado As Match

For Each encontrado In encontrados

'Concateno a string com o resultado
strRetorno = strRetorno + encontrado.Value
Next

SomenteNumeros = CInt(strRetorno)

End Function

Beleza, até agora apenas uma forma diferente de verificar números, porém, e se quisermos criar um método que retorne apenas String? Tradicionalmente faríamos uma lógica que faria um for, verificaria se é número e não concatenaria. Com regex bastaria alterarmos o Pattern, que ficaria assim:

regex.Pattern = “^[0-9]”

Pronto! Pois, o “^” indica negação, ou seja, tudo que não for digito (numero) de 0 à 9.

Agora vamos um pouco além. Imagine que você tem um gerador de relatório, com vários formatos. Imagine o trabalho para configurar cada relatório, com padrões totalmente diferente, completar com espaço, com zeros, com quaiquer caracteres. Imagine se você pudesse fazer algo assim:

Suponha que sua Tabela seja tbCliente e que tenha os campos IDCliente, NomeCliente, DataNascimento.

e que pudesse simplesmente definir o formato, como por exemplo:

Select: Select * from tbCliente

Formato: {IDCliente:0000}{NomeCliente:!@           }{DataNascimento:dd/mm/yyyy}

Como você faria isso?… no próximo artigo vou mostrar como podemos fazer isso de uma forma muito simples!

Até a próxima.

 
teste