Tag Archives: c#

Melhorando a legibilidade do C# com Extension Methods

É difícil achar alguém que não goste da sintaxe do Ruby, é simples e agradável, tanto para ler quanto para escrever. Muitas vezes as instruções se tornam verdadeiras frases e parece que você está lendo um artigo e não um código. Olha como fica um loop em Ruby.

5.times { puts "Hi" }

“5 vezes imprima Hi”. O melhor de tudo é que é possível termos algo muito semelhante em C#, fica assim.

//New Style
5.Times((i) => {
    Console.WriteLine(i);
});

//Old Style
for(int i = 0; i < 5; i++) {
    Console.WriteLine(i);
}

Ok, um pouco mais verboso que o exemplo em Ruby, mas ainda assim é muito agradável. Para conseguirmos usar o exemplo acima é preciso incluir este pequeno extension method.

public static void Times(this int times, Action<int> action)
{
    for (int i = 0; i < times; i++)
        action(i);
}

Extension Methods, adoro :)
São várias as possibilidades de extensão, basta usar a criatividade.

//Loop de 5 até 10
5.To(10, (i) => {
    Console.WriteLine(i);
});

//string.IsNullOrEmpty() é chato demais, que tal isso?
string nome = "Guilherme";
if (nome.IsNullOrEmpty()) {
    Console.WriteLine("Nome está vazio");
}

//3.Minutes(), 10.Seconds(), 2.Hours(). nuff said
Thread.Sleep(3.Minutes());

A implementação fica assim.

public static bool IsNullOrEmpty(this string value)
{
    return string.IsNullOrEmpty(value);
}

public static void To(this int start, int end, Action<int> action)
{
    for (int i = start; i <= end; i++)
        action(i);
}

public static TimeSpan Minutes(this int minutes)
{
    return TimeSpan.FromMinutes(minutes);
}

public static TimeSpan Hours(this int hours)
{
    return TimeSpan.FromHours(hours);
}

public static TimeSpan Minutes(this int seconds)
{
    return TimeSpan.FromSeconds(seconds);
}

Dica: Quer conhecer uma infinidade de métodos legais e criativos? Este tópico no StackOverflow posusi vários métodos enviados pela comunidade. Escolhas os que mais lhe agradam. Tem também o projeto Fluent DateTime no CodePlex, pode ser útil para aqueles que precisam utilizar datas.

CSharpista falando Javanês, minha opinião sobre o Java


Até duas semanas atrás, meu conhecimento de Java beirava o nulo. Eu já conhecia a sintaxe, afinal, é parecida com C#. Conhecia alguns frameworks famosos também, como o Hibernate e log4j, mas colocar a mão na massa, nunca.

O projeto em que eu iria iniciar tinha como pré-requisito ser escrito em Java, com isso, tive que aprender linguagem e alguns de seus frameworks. Foi e está sendo uma experiência bem legal, e por isso resolvi compartilhar ela, bem como falar um pouco da minha opinião sobre o Java.

Sintaxe e Padrões

Preciso adminir que sou fã da forma como é implementado o get/set em C#, acho o resultado muito mais legível e de fácil compreensão. Um pequeno comparativo:

Em C#:

//definição
public class Cliente
{
    public string Nome { get; set; }
    public int Idade { get; set; }
}

//uso
public class ClienteController
{
    public void Adicionar()
    {
        Cliente cliente = new Cliente();
        cliente.Nome = "João Salsa";
        cliente.Idade = 23;

        if (cliente.Idade > 20)
        {
            //stuff
        }
    }
}

Em Java:

//definição
public class Cliente {
    private String nome;
    private Integer idade;

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getNome() {
        return this.nome;
    }

    public void setIdade(Integer idade) {
        this.idade = idade;
    }

    public String getIdade() {
        return this.idade;
    }
}

//uso
public class ClienteController {
    public void adicionar() {
        Cliente cliente = new Cliente();
        cliente.setNome("João Salsa");
        cliente.setIdade(23);

        if (cliente.getIdade() > 20) {
            //stuff
        }
    }
}

Self-explanatory, além de menor, fica mais fluente, não?

A questão das chaves também me chamou a atenção. Tanto no PHP quanto no Java, o padrão é utilizar as chaves na mesma linha da instrução, já no C#, na linha abaixo. Neste ponto eu fico com o padrão do Java. Compare o if dos dois códigos acima, se no lugar do comentário “//stuff” tivesse realmente uma única instrução, no Java ficaria mais junto e fácil de ler. Eu sei que não há necessidade de se usar chaves nestes casos, mas eu gosto.

IDE (eclipse)

Algumas hotkeys do eclipse são interessantes, por exemplo, o CTRL+SHIFT+T. Este atalho abre uma janela para pesquisar classes pelo nome usando wildcards, * e ?. Vejam a imagem abaixo:


Imagem retirada de Java Place Blog

Existe isso no Visual Studio? Eu quero :D

Outro recurso do eclipse que gostei bastante foi o do highlight que ele faz quando você clica em alguma variável ou método, vejam só:


Imagem retirada de satukubik

Ah, outro detalhe importante. Levei menos de 2 minutos para “instalar” o eclipse contra as quase 1 hora que leva o Visual Studio. Copy and Paste definitivamente é melhor que Next, Next, Finish. E isso ocorreu com tudo o que eu precisei instalar de Java na máquina: Tomcat, Eclipse e JBoss. Apenas a JDK foi no instalador. Kick ass, definitivamente.

Frameworks

Até o momento tive pouco contato com os frameworks Java, mas é impossível não falar do maven. Caramba, que fantástico, é muito útil mesmo, e até o momento não tive nenhum problema com ele. De forma simplificada, é um framework onde você define quais são as dependências do seu projeto e ele se encarrega de montar seu projeto com todas as dependências definidas, fazendo download e adicionando as referências necessárias.

Outros frameworks que tive contato foram Struts2 e JSF. Pelo o que pudi perceber, o JSF é para o ASP.NET WebForms o que o Struts2 é para o ASP.NET MVC. Eu, sendo fã de ASP.NET MVC, optei por usar Struts2. De modo geral, eu estou gostando, alguns itens como model binding e configuração deixam a desejar. A configuração é toda feita em arquivos *.xml e cada dia que passa os xml estão ficando maiores. Saudade do ASP.NET MVC onde eu configurava as rotas via C# e com sintaxe fluente…

Tirando essa parte da configuração, achei bem fácil de customizar os filters, results e interceptor, não tive que ir em nenhum tutorial, descobri sozinho, e isso só mostra o quanto é fácil.

Quanto ao JSF, um dia foi suficiente para eu largá-lo. Muita semelhança com o ASP.NET WebForms me deixou com medo, a falta de controle no HTML foi um dos motivos maiores, além disso a curva de aprendizado do JSF foi maior que o Struts2. Não fui muito a fundo no JSF, posso ter me enganado, mas a primeira impressão não agradou.

Comunidade

Aqui é que geralmente a maior partes das intrigas são geradas. Conforme este meu post, acho o GUJ um excelente fórum de discussão de alto nível. Vejo que falta isso na comunidade .NET, as dúvidas que surgem em alguns fórum são geralmente relacionados às funções de wizard e drag and drop do Visual Studio. É mais fácil achar uma discussão de algum design pattern ou arquitetura em um grupo de Java do que em um de C#.

Felizmente as coisas estão mudando, a grande movimentação que há no grupo de discussão .Net Architects prova que existe muita gente interessada em aprender e discutir este tipo de assunto.

Conclusão

Cada linguagem/plataforma tem seu espaço e momento, nunca vi uma discussão entre duas linguagens que tivesse um fim. Além disso, cada pessoa tem sua preferência e sua opinião, e devemos saber respeitá-las. Eu, por exemplo, não me dou bem com Ruby, já tentei, mas não consigo, eu prefico ficar com PHP e Python. Não digo que Ruby é ruim ou qualquer coisa do tipo, apenas não gosto. Eu não gostava de Java até então, achava tudo muito complicado, agora já estou mudando de opinião, conforme eu fui aprendendo, fui vendo que não é um bixo de 7 cabeças.

Gostei de Java, adorei a oportunidade que estou tendo de aprender, consegui sair um pouco do meu mundinho csharpista e abriu algumas portas em minha mente, porém, minha preferência continua sendo C#, I love it <3 :D

Dica #5: Escondendo teclado no Windows Mobile com C#

Olá a todos,

Neste post vou explicar como remover o teclado dos smartphones que possuem windows mobile. Além disso, vou repassar uma dica de como utilizar esse recurso com maior eficiência, prontos?

Porque eu deveria esconder o teclado?

Talvez você esteja se perguntando isso neste momento, é simples, imagine uma tela onde há apenas botões e nenhum campo para digitar, faz sentido dar ao usuário um teclado que ele não vai usar? É muito mais prático remover o teclado e evitar que ele aperte acidentalmente e deixar apenas o que importa na tela.

Como fazer?

Essas funções que envolvem alterações no core são feitas através de P/Invoke. Basicamente, são chamadas feitas à DLLs do próprio sistema operacional através do C#.

Sem mais delongas, vou colocar aqui uma classe com um método para remover o teclado, e é claro, outro para fazer o teclado aparecer novamente.

public static class Keyboard
{
    [DllImport("coredll.dll")]
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("coredll.dll")]
    private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

    [DllImport("coredll.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private static void SetSipButton(bool show)
    {
        IntPtr hSipWindow = FindWindow("MS_SIPBUTTON", "MS_SIPBUTTON");
        if (hSipWindow != IntPtr.Zero)
        {
            IntPtr hSipButton = GetWindow(hSipWindow, 5);
            if (hSipButton != IntPtr.Zero)
                ShowWindow(hSipButton, (show) ? 1 : 0);
        }
    }

    public static void Hide()
    {
        SetSipButton(false);
    }

    public static void Show()
    {
        SetSipButton(true);
    }
}

Para usar é muito fácil. Quer esconder o teclado? Basta escrever:

Keyboard.Hide();

E agora você quer fazer o teclado voltar ao normal?

Keyboard.Show();

Difícil? :}

Agora há um problema, se você colocar isso em todo formulário que você for fazer, você vai repetir este código x vezes, onde x é a quantidade de formulários que você possui.
No coméco eu disse que eu daria uma dica, e a dica é para resolver isso.

Dica

Crie dois formulários que servirão de base. Chame um de KeyboardForm e outro de NoKeyboardForm, faça com que ambos formulários herdem de Form.

No formulário KeyboardForm coloque o código para MOSTRAR o teclado, no formulário NoKeyboardForm coloque o código para ESCONDER o teclado.

Toda novo formulário que você criar, ao invés de herdar de Form (padrão), faça ele herdar de KeyboardForm caso sua tela tenha necessidade de um teclado, caso contrário, herde de NoKeyboardForm.

Simples, elegante, eficiente, e como diria o Steve Jobs, “amazing”, “incredible”, “awesome”, “great”.

Abaixo estou deixando um pacote com uma solução que eu fiz no Visual Studio 2008 com exemplos de uso. É só baixar, abrir e executar.

Clique aqui para fazer o download de 'Removendo teclado no Windows Mobile' (40.28 kB)

Espero ter ajudado.

Configurar NHibernate em um projeto Web

Neste tutorial vou explicar como dar o primeiro passo com o NHibernate. A configuração não é nada trivial e por isso gera bastante dúvidas.

Vou estar usando a versão mais recente do NHibernate até o momento, se você quiser usar a mesma versão, utilize este link para fazer o download.

Primero passo, criando a estrutura de projetos

Abra o Visual Studio, crie um projeto Web Application e uma Class Library na mesma solução. Vai ficar assim:

Obs.: Eu tenho o costume de deletar a pasta App_Data e a classe Class1 porque não vou utilizar.

Segundo passo, criando o arquivo de configuração

Dentro do projeto Class Library, crie um xml e chame-o de hibernate.cfg.xml. Atenção, é hibernate e não nhibernate!

Dentro deste arquivo ficam as configurações do banco de dados que iremos usar. Aqui será informado qual o provider (sqlserver, mysql, oracle etc), qual a string de conexão, dialeto etc.

Estou usando MSSQL Server e meu arquivo de configuração ficou assim:


<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
 <session-factory name="NHibernate">
 <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
 <property name="connection.connection_string">Server=(local);initial catalog=MinhaBase;Integrated Security=SSPI</property>
 <property name="show_sql">false</property>
 <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
 <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
 <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
 <mapping assembly="MercadoVader.NHibernateModule" />
 </session-factory>
</hibernate-configuration>

Obs.: A única configuração que muda entre meu arquivo e o seu será a string de conexão. No meu caso estou usando localhost com um banco de dados chamado e usando windows authentication.

Clique com o botão direito no arquivo hibernate.cfg.xml e vá em suas propriedades, na opção Copy to Output Directory escolha o valor Copy Always.

Terceiro passo, banco de dados

Não há muito segredo aqui, apenas crie uma base de dados e rode este script para criar uma tabela de produtos.


CREATE TABLE [dbo].[PRODUTO](
 [ID] [int] IDENTITY(1,1) NOT NULL,
 [NOME] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
 [PRECO] [decimal](18, 2) NOT NULL,
 [DATA_CADASTRO] [datetime] NOT NULL,
 CONSTRAINT [PK_PRODUTO] PRIMARY KEY CLUSTERED
(
 [ID] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

Terceiro passo, banco de dados

Não há muito segredo aqui, apenas crie uma base de dados e rode este script para criar uma tabela de produtos.


CREATE TABLE [dbo].[PRODUTO](
 [ID] [int] IDENTITY(1,1) NOT NULL,
 [NOME] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
 [PRECO] [decimal](18, 2) NOT NULL,
 [DATA_CADASTRO] [datetime] NOT NULL,
 CONSTRAINT [PK_PRODUTO] PRIMARY KEY CLUSTERED
(
 [ID] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

Quarto passo, criando um HttpModule pro NHibernate

Essa parte é mais chata, primeiro de tudo, selecione o projeto Class Library e adicione referência à NHibernate.dll que está na pasta Required_Bin dentro do arquivo zip que foi baixado no início do tutorial. Adicione também uma referência à NHibernate.ByteCode.Castle que também veio no arquivo zip. Por último, adicione referência à System.Web, será necessário para poder criar uma classe que herde da System.Web.IHttpModule.

Crie uma classe chamada NHibernateSessionModule dentro da Class Library e coloque este conteúdo nela:

public class NHibernateSessionModule : IHttpModule
{
    public static readonly string KEY = "NHibernateSession";
    private static ISession _session;

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
        context.EndRequest += new EventHandler(context_EndRequest);
    }

    private void context_EndRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;

        ISession session = context.Items[KEY] as ISession;
        if (session != null)
        {
            try
            {
                session.Flush();
                session.Close();
            }
            catch { }
        }
        context.Items[KEY] = null;
    }

    private static ISessionFactory factory = null;

    private static ISessionFactory GetFactory()
    {
        if (factory == null)
        {
            Configuration config = new Configuration();
            if (config == null)
                throw new InvalidOperationException("NHibernate configuration is null.");

            config.Configure();

            factory = config.BuildSessionFactory();
            if (factory == null)
                throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
        }
        return factory;

    }

    public static ISession OpenSession()
    {
        ISession session;
        session = GetFactory().OpenSession();
        if (session == null)
            throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
        return session;
    }

    public static ISession CurrentSession
    {
        get
        {
            if (HttpContext.Current == null)
            {
                if (_session != null)
                {
                    return _session;
                }
                else
                {
                    _session = OpenSession();
                    return _session;
                }
            }
            else
            {
                HttpContext currentContext = HttpContext.Current;
                ISession session = currentContext.Items[KEY] as ISession;
                if (session == null)
                {
                    session = OpenSession();
                    currentContext.Items[KEY] = session;
                }
                return session;
            }
        }
    }

    private void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
        context.Items[KEY] = OpenSession();
    }
}

Pelo fato de esta classe herdar de IHttpModule, ela será chamada toda vez que um HttpRequest for feito para sua aplicação Web. Esta classe cria uma objeto do tipo Session para cada request e só destroi ele no final.Isso garante que teremos apenas uma Sessão aberta para cada request.

Essa parte não é necessária fazer, mas é considerado uma boa prática trabalhar com apenas uma Sessão ao invés de sair criando várias.

Abra o arquivo web.config e procure pela tag httpModules, dentro desta tag adicione mais um valor, que será referência ao módulo que acabamos de criar. Fica assim:

<httpModules>
 <add name="NHibernateSessionModule" type="MercadoVader.NHibernateModule.NHibernateSessionModule, MercadoVader.NHibernateModule"/>
 <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</httpModules>

Quinto passo, o mapeamento

Ufa, quase acabando :)

Dentro da Class Library crie uma classe chamada Produto. Crie também uma pasta chamada Mapping e dentro dela crie o arquivo Produto.hbm.xml.

A classe produto fica assim:

public class Produto
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public DateTime DataCadastro { get; set; }
    public decimal Preco { get; set; }
}

O arquivo Produto.hbm.xml fica assim:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="MercadoVader.NHibernateModule" assembly="MercadoVader.NHibernateModule">

  <class name="Produto" table="PRODUTO">

    <id name="Id">
      <column name="ID" sql-type="int" not-null="true"/>
      <generator class="identity" />
    </id>

    <property name="Nome" type="String">
      <column name="NOME" length="100" not-null="true" />
    </property>

    <property name="Preco" type="Decimal">
      <column name="PRECO" precision="18" scale="2" not-null="true" />
    </property>

    <property name="DataCadastro" type="DateTime">
      <column name="DATA_CADASTRO" not-null="true" />
    </property>
  </class>

</hibernate-mapping>

O que estamos fazendo aqui é criar uma classe que é espelho da nossa tabela no banco de dados e também criando um arquivo de mapeamento que liga a classe com a tabela, nada muito complexo.

Clique com o botão direito no arquivo Produto.hbm.xml e vá em suas propriedades. Na opção Build Action selecione o valor “Embedded Resource”, isso fará com que o arquivo seja compilado dentro de uma DLL.

Sexto passo, será que funciona funciona?

Para testar, você deve selecionar o projeto Web e adicionar referência ao projeto Class Library e também à NHibernate.dll.

Feito isso, entre no Default.aspx.cs e coloque isso no Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    Produto produto = new Produto();
    produto.Nome = "Biscoito Trakinas";
    produto.Preco = 1.10M;
    produto.DataCadastro = DateTime.Now;
    NHibernateSessionModule.CurrentSession.Save(produto);
}

Se tudo der certo, deverá haver um registro salvo no banco de dados agora.
Deu certo? Parabéns, o NHibernate está configurando e funcionando.
Não deu? Faça um comentário descrevendo o erro e verei se consigo ajudar.

Documentação do NHibernate está aqui: https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/

Utilize a documentação para aprender sobre HQL e como buscar dados do banco de dados.
Conforme eu havia comentado neste post, o site summer of nhibernate é muito bom para aprender.
Se eu escrevi algo errado, por favor, me corrijam, já é meio tarde e o sono já está batendo.

Aqui está o projeto que eu criei para download.

Clique aqui para fazer o download de 'MercadorVader, NH + ASP.NET' (1.09 MB)

Até a próxima!

Dica #2: Formatando datas em formato e língua específica

Neste post do C# Brasil você consegue ver alguns dos formatos de datas possível da classe DateTime. Muitas vezes você precisa de um formato mais específico, como por exemplo, ‘Agosto, 2009′ ou ‘sábado, 29 de janeiro de 2009′.

Na lista abaixo você confere os possíveis valores de se obter usando o método ToString da classe DateTime.

Código Resultado Exemplo
HH Hora (de 0 até 23)
hh Hora (de 0 até 12)
mm Minutos
MM Mês 08, 02, 12
MMM Mês jun, ago, jan, dez
MMMM Mês agosto, setembro, outubro
dd Dia 21,10,20
ddd Dia da semana sáb, seg, ter
dddd Dia da semana sábado, segunda, terça
yy Ano 09,08,89,90
yyyy Ano 2009,2008,1989,2010

Veja alguns exemplos de como usar, e também qual o resultado.

DateTime.Now.ToString("dddd, dd 'de' MMMM 'de' yyyy"); // sábado, 22 de agostro de 2009
DateTime.Now.ToString("MMMM, yyyy"); // agostro, 2009
DateTime.Now.ToString("'dia' dd 'de' MMMM 'de' yyyy"); // dia 22 de agostro de 2009
DateTime.Now.ToString("HH:mm 'do dia' dd"); // 18:17 do dia 22
DateTime.Now.ToString("hh:mm 'do dia' dd"); // 06:17 do dia 22

Eu particularmente gosto de usar esses formatos ao invés de apenas uma letra como foi mostrado no C# Brasil, fica mais explícito e outra pessoa vai conseguir ler com mais clareza.

Por default o resultado sairá na língua atual do sistema operacional que está executando o programa, se você quer executar em uma língua específica, você pode fazer assim:

Thread.CurrentThread.CurrentCulture = new CultureInfo("nl-NL");
Console.WriteLine(DateTime.Now.ToString("dddd, MMMM")); //zaterdag, augustus

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Console.WriteLine(DateTime.Now.ToString("dddd, dd 'de' MMMM 'de' yyyy")); //Saturday, August

Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
Console.WriteLine(DateTime.Now.ToString("dddd, dd 'de' MMMM 'de' yyyy")); //sábado, agosto

Esqueci de algo?

Sharing Buttons by Linksku