terça-feira, 29 de setembro de 2009

Funcionalidade de classe e membro static

Desde o último mês ando participando com grande frequência dos fóruns da msdn, e faz alguns dias que respondi uma dúvida da classe static. Porém ao responder as perguntas fui respondendo algumas coisas que não havia pensado sobre ela, como ocupação de memória, performance e velocidade.
Estou aqui para mostrar como foi a discussão porém como uma explicação.
O que é um membro static? Um menbro static é um membro de uma classe que terá o mesmo valor em todas as partes do código, por exemplo, considere uma classe

class MinhaClasse
{
public int Valor;
public static int ValorCompartilhado;
}

Qual a diferença entre Valor e ValorComparilhado? É o seguinte se você fizer:

MinhaClasse c = new MinhaClasse();
c.Valor = 2;

O 2 comente será visível para a instância c, agora caso você faça MinhaClasse.ValorCompartilhado = 2 o 2 será visível em todo o programa e em todas as partes que você faça int v = MinhaClasse.ValorCompartilhado a v será atribuido 2.

O que é uma classe static? Uma classe static só poderá conter membros static, assim no exemplo anterior teríamos que mudar int Valor para static int Valor.

Quando usar uma classe ou membro static? Primeiro vou responder a membors static, fica óbvio que se você precisa utilizar uma mesma instancia ou valor em todo o programa, imagine por exemplo uma instancia de uma conexão com o banco, você usará uma instancia dessa conexão como static. E classe? Classe static é muito utilizado para classes que contém apenas métodos ou então àquelas em que você após analisar verá que todos seus membros ficariam melhor como static, pois seus valores são compartilhados em todo o programa.

Discutiremos agora a parte de memória, desempenho e velocidade, para isso vamos levar em consideração estas duas classe:

public static class ClasseStatic
{
private static OutraClasse oc = new OutraClasse();
public static int Calculo = oc.Calcular();
public static string Nome = oc.RetornaNome();
}

public class ClasseNaoStatic
{
private OutraClasse oc = new OutraClasse();
public int Calculo = oc.Calcular();
public string Nome = oc.RetornaNome();
}

O que a OutraClasse faz não nos importa, analisaremos outras coisas.

Memória:
Considerando a classe static nós teremos:
OutraClasse = 1
int = 1
string = 1

Agora considerando a classe não static nós teremos os dados acima a cada nova instancia dela, fazendo então por exemplo:
ClasseNaoStatic ns1 = new ClasseNaoStatic();
ClasseNaoStatic ns2 = new ClasseNaoStatic();
Você terá:
OutraClasse = 2
int = 2
string = 2

Tendo assim um consumo menor de memória para a classe static.

Performance e velocidade:
Como chamamos dois métodos da classe OutraClasse para atribuir a Calculo e Nome e considerando uma velocidade para este método retornar, então teremos um tempo menor para a classe static, e levando a atribuição na pilha de métodos podemos ver uma melhor performance na classe static também.

Por que então não usar sempre static?
Imgine a seguinte situação, uma classe que controla quais usuários estão usando seu sistema, se for static e cada vez que um novo usuário entrar no sistema, você atribuir seu nome por exemplo ao membro static, você perderá os outros pois todo o programa agora usará o novo valor.

Conclusão:
Use static quando você ver a necessidade de seus dados terem o mesmo valor em todo o programa e uma mudança nele afete também todo o programa.

Para ver como foi a discussão no fórum segue o link:
http://social.msdn.microsoft.com/Forums/pt-BR/vscsharppt/thread/95bf6774-0d70-4cec-b1bd-20b9eeb4d030

segunda-feira, 31 de agosto de 2009

Usando javascript para percorrer Repeater

Hoje entrei em uma situação na qual nunca tinha passado, me pediram para fazer uma função em javascript para percorrer os checkbox de um repeater e analisar se pelo menos um estava checado.
O único problema é que o Visual Studio gera código pra você sobrescrevendo o nome e o id que você deu quando se usa usercontrol, assim um name="chkPassenger" se tranformou em: mUsrMain_UsrWebCheckInPassengersByFlight1_rptPNRSegments_ctl00_rptPassengers_ctl02_chkPassenger,
tudo bem ele gerou um span com o name correto, mas eu queria encontrar diretamente o checkbox.
A solução foi escrever este código:

function GetAllCheckBox()
{
var count = 0;
var inputs = document.getElementsByTagName('input');
for(var i = 0; i < inputs.length; i++)
{
      if(inputs[i].type == 'checkbox' && inputs[i].name.indexOf('chkPassenger') != -1)
     {
            if(inputs[i].checked == true)
            {
                   count++;
                   break;
            }
     }
}

if(count == 0)
      return false;
return true;
}

O porque do return? Bem como este evento estava sendo gerado por um itemcommand ele estava dando postback e claro, se eu precisava fazer em javascript era justamente para evitar ele. Para cancelar um postback, adicione a seguinte propriedade no controle que gerará ele:

OnClienteClick="return GetAllCheckBox();"

Assim se retornar false ele cancelará o postback, caso contrário o postback ocorrerá normalmente.

terça-feira, 25 de agosto de 2009

Adicionando imagens no Crystal Report

Uma das coisas mais comuns a se fazer em software, é a possibilidade de fazer um resumo de vendas para que o usuário possa escolher entre salvar em diversos formatos ou então imprimir.
Para que isso seja feito com facilidade, Visual Studio possui além dos modelos de documentos da Microsoft, uma ferramenta poderosa chamada Crystal Report.
Infelizmente o Crystal Report não possui um campo mapeado para imagem, onde você possa adicionar apenas uma url e ele faça todo o trabalho para você. Você pode estar pensando "mas também o que mais ele quer?", porém isso é comum quando se trabalha com a classe Image do .NET.
Para realizar esse trabalho é necessário adicionar um array de bytes.

Em seu datasource crie um atributo byte[] por exemplo:

    public byte[] Image { get; set; }

Feito isso de um refresh no seu datasource no Crystal Report para que você possa visualizar o novo campo, após visualizado apenas arraste o novo campo para o report.

Adicione o namespace: using System.IO;

Agora para ler a imagem de seu disco adicione o seguinte código:

    FileStream stream = new FileStream(url, FileMode.Open, FileAccess.Read);
    BinaryReader reader = new BinaryReader(stream);
    suaClasse.Image = reader.ReadBytes(Convert.ToInt32(stream.Length));
    reader.Close();
    stream.Close();

Vincule o datasource do Crystal Report para uma lista de sua classe ou o seu dataset e então o Crystal Report poderá realizar o trabalho para você.