Pesquisa

quinta-feira, 26 de março de 2009

Acessando código fonte do .NET Framework

Com o lançamento do Visual Studio 2008 e do .NET Framework 3.5 a Microsoft anunciou publicamente a liberação de acesso ao código fonte para leitura durante o debug mediante concordância com os termos de licenciamento. Vale lembrar que as versões Express (gratuitas) não terão acesso a essa funcionalidade.
Para ter o acesso você precisa rodar um hotfix que vai atualizar o Visual Studio 2008 de forma a suportar os downloads dos arquivos de Symbols com as informações necessários ao debug.
As classes abaixo estão disponíveis para utilização:

  1. .NET Base Class Libraries (including System, System.CodeDom, System.Collections, System.ComponentModel, System.Diagnostics, System.Drawing, System.Globalization, System.IO, System.Net, System.Reflection, System.Runtime, System.Security, System.Text, System.Threading, etc).
  2. ASP.NET (System.Web, System.Web.Extensions)
  3. Windows Forms (System.Windows.Forms)
  4. Windows Presentation Foundation (System.Windows)
  5. ADO.NET and XML (System.Data and System.Xml)

Siga os procedimentos abaixo para configuração:

  1. Instale o hotfix Visual Studio 2008 QFE
    https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=10443&wa=wsignin1.0
    Pode ocorrer um erro durante a instalação desse fix caso você tenha uma versão anterior (beta 2) instalado. Para resolver basta colocar o dvd do Visual Studio 2008 no drive.
  2. Configurando o Visual Studio 2008
    Inicie o VS2008 e vá em Tools > Options > Debugging
    a) Para iniciar o debug do código fonte desmarque a opção: Enable Just My Code (Managed only)
    b) Certifique de marcar a opção: Enabled source server support



  3. Configurando arquivo Symbols
    O Visual Studio 2008 vai automaticamente baixar os arquivos necessários para o debug do código fonte. Para isso você precisa seguir os passos de configuração abaixo:

    a) Adicione a referência para : http://referencesource.microsoft.com/symbols
    b) Defina a pasta que será salvo os arquivos de debug.
    c) Marque a opção: "Search the above loactions only when symbols are loaded manualy" (Download manual)
    d) Você pode optar também por não marcar a opção citada na letra "c" que o Visual Studio vai fazer download automático, porém pode demorar a depender da conexão internet (+- 50 MB). (Recomendado após os primeiros testes)
    Configurando Symbol

  4. Iniciando depuração do código
    Chegou o tão esperado momento de colocar em prática os conhecimentos e explorar o .NET por dentro.

    a) Coloque seu break point dentro do seu código.
    b) Rode o projeto.
    c) Localize a janela Call Stack ou chame com o atalho: CTRL + ALT + C .
    d) Selecione na janela Call Stack as referências e depois Load Symbols conforme figura 03 (download manual).
    e) Durante o processo de debug o Visual Studio vai salvar os arquivos de Symbols na pasta cache. Janela Call Stack

Definida as configurações você já pode colocar em prática e avaliar por exemplo a implementação do método DataBind de um GridView. Confira nas duas figuras seguintes:
Parte 1 - Colocando Break Point no DataBind()

GridView / DataBind

Parte 2 - Navegando pelo método DataBind() usando "F11"

DataBind

Parte 3 - Avaliando a implementação do DataBind do GridView diretamente no código fonte.

Dentro do método DataBind.

Com esse processo os desenvolvedores mais curiosos agora podem finalmente enxergar em tempo real o que está acontecendo nas chamadas de métodos internos do .NET.
Referências:
- . NET Framework Library Source Code now available
- Configuring Visual Studio to Debug .NET Framework Source Code

Créditos: Ramon Durães - http://www.linhadecodigo.com.br/Artigo.aspx?id=1655

sexta-feira, 13 de fevereiro de 2009

Passagem de parâmetros

Em C#, os parâmetros podem ser passador por valor ou por referência. Passando parâmetros por referência permite que o método altere o valor do parâmetro passado e as mudanças persistem após a passagem do método.

Passando uma variavel do tipo Valor para um método significa passar uma cópia da variável para o método. Quaisquer alterações ao parâmetro que ocorrem no interior do método não tem nenhum efeito sobre os dados originais armazenadas na variável. Se você quiser que o chamado método para alterar o valor do parâmetro, você tem que passá-la por referência, usando a palavra ref.

Passagem de parâmetro tipo Valor, por Valor:

// PassingParams1.cs 
using System;
class PassingValByVal
{
static void SquareIt(int x)
// O parametro x é chamado por Valor.
// Alterações no x não afetarão o valor original do myInt.
{
x *= x;
Console.WriteLine("O valor antes de chamar o método: {0}", x);
}
public static void Main()
{
int myInt = 5;
Console.WriteLine("O valor antes de chamar o método: {0}",
myInt);
SquareIt(myInt); // Passing myInt by value.
Console.WriteLine("O valor após chamar o método: {0}",
myInt);
}
}
Saida:
O valor antes de chamar o método: 5
O valor dentro do método: 25
O valor após chamar o método: 5
Explicação: A variável myInt sendo um tipo de valor contém seus dados (o valor 5). Quando SquareIt é chamado, o conteúdo do myInt é copiado para o parâmetro x que é multiplicado por ele mesmo dentro do método. No Main porém, o valor de myInt é o mesmo, antes e depois de chamar o método SquareIt. Logo, a mudança que ocorre no interior do método afeta somente a variável local x.

Passagem de parâmetro tipo Valor, por Referencia:

// PassingParams2.cs 
using System;
class PassingValByRef
{
static void SquareIt(ref int x)
// O parametro x é passado por referencia.
// Alterações no x afetarão a conteudo do myInt.
{
x *= x;
Console.WriteLine("O valor dentro do método: {0}", x);
}
public static void Main()
{
int myInt = 5;
Console.WriteLine("valor antes de chamar o método: {0}",
myInt);
SquareIt(ref myInt); // Passing myInt by reference.
Console.WriteLine("O valor após chamar o método: {0}",
myInt);
}
}
Saida:
O valor antes de chamar o método: 5
O valor dentro do método: 25
O valor após chamar o método: 25
Neste exemplo, não é o conteudo de myInt que é passado, mas sim, uma referência à myInt. O parâmetro x não é um int, mas sim uma referência a um int (neste caso, uma referência à myInt). Portanto, quando x é multiplicado por ele mesmo dentro do método, o que realmente é multiplicado é o conteudo da variavel refenciada por x, no caso, myInt.

Passando de parâmetros do tipo Referência, por Valor:

// PassingParams4.cs 
// Passing an array to a method without the ref keyword.
using System;
class PassingRefByVal
{
static void Change(int[] arr)
{
arr[0]=888; // Essa alteraçao ocorre na variavel original.
arr = new int[5] {-3, -1, -2, -3, -4}; // Alteração somente local.
Console.WriteLine("Dentro do método, o primeiro elemento é: {0}", arr[0]);
}

public static void Main()
{
int[] myArray = {1,4,5};
Console.WriteLine("Dentro do Main, antes de chamr o método, o primeiro elemento é: {0}", myArray [0]);
Change(myArray);
Console.WriteLine("Dentro do Main, depois de chamr o método, o primeiro elemento é: {0}", myArray [0]);
}
}
Saida:
Dentro do Main, antes de chamr o método, o primeiro elemento é: 1
Dentro do método, o primeiro elemento é: -3
Dentro do Main, depois de chamr o método, o primeiro elemento é: 888
No exemplo anterior, a matriz, myArray que é um tipo Referência, ela é passada para o método sem o parâmetro ref. Nesse caso, uma cópia da referência, o que aponta para myArray é passada para o método. O resultado mostra que é possível que o método para alterar o conteúdo de um elemento matriz (de 1 a 888). No entanto, alocando uma nova parte de memória usando o operador new no interior do método Change faz com que a variável arr referência uma nova matriz. Assim, quaisquer alterações depois disso que não irá afetar a matriz original, myArray ,que foi criada no interior Main. Na verdade, duas matrizes são criadas neste exemplo, dentro do Main e uma no interior do método Change.

Passando de parâmetros do tipo Referência, por Referencia:


// PassingParams5.cs 
// Passando um array para um método utilizando ref.
// Compare com o exemplo anterior.
using System;
class PassingRefByRef
{
static void Change(ref int[] arr)
{
// As duas operaçoes alterarão o a variavel original.
arr[0]=888;
arr = new int[5] {-3, -1, -2, -3, -4};
Console.WriteLine("Dentro do método, o primeiro elemento é: {0}", arr[0]);
}

public static void Main()
{
int[] myArray = {1,4,5};
Console.WriteLine("Dentro principal, antes de chamar o método, o primeiro elemento é o seguinte: {0}", myArray [0]);
Change(ref myArray);
Console.WriteLine("Dentro principal, depois de chamar o método, o primeiro elemento é: {0}", myArray [0]);
}
}
Saida:
Dentro principal, antes de chamar o método, o primeiro elemento é o seguinte: 1
Dentro do método, o primeiro elemento é: -3
Dentro principal, depois de chamar o método, o primeiro elemento é: -3
Todas as mudanças que ocorrem no interior do método afeta a variavel original. De fato, o array original é reatribuídos usando o operador new. Assim, depois de chamar o método Change, qualquer referência a um dos ponto do myArray persistirá o valor alterado no método.

Mais informações:

http://msdn.microsoft.com/en-us/library/0f66670z(vs.71).aspx

http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

http://msdn.microsoft.com/en-us/library/490f96s2.aspx

Créditos: Rodrigo Araujo, Márcio Martins, eu.

quinta-feira, 5 de fevereiro de 2009

Duas aplicações usando o mesmo usuário da menbership

Para ser utilizado em dois projetos do tipo asp.net web site diferentes a mesma validação de usuário da membership, basta que a tag machineKey do web.config esteja igual para os dois asp.net web site .
...
<system.web>
...
<machinekey validationkey="51305CA9CB21F4F1422FF158A5B42D0E8DN8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE" decryptionkey="8A9BE8FD67AF6979E7D20198CFAA50DD3D3799C77AF2B72F" validation="SHA1">
</machinekey>
</system.web>
...

terça-feira, 3 de fevereiro de 2009

DefaultButton e similar

No framework 2.0 e 3.5 um controle HtmlForm tem a propriedade DefaultButton.
O DefaultButton será o botão acionado quando a tecla enter for precionada na página.
this.Form.DefaultButton = btnFiltrar.UniqueID;
Já no framework 1.1 não existe essa propriedade. Então, para que um botão seja acionado basta utilizar o seguinte código:
Page.RegisterHiddenField("__EVENTTARGET", btnFiltrar.UniqueID);

Quantos meses separa duas datas

Para saber a diferença, em meses entre duas datas basta aplicar o seguinte método:
private static int DiferencaEmMeses(DateTime comeco, DateTime fim)
{
 int diferenca = 12 * (comeco.Year - fim.Year) + comeco.Month - fim.Month;
 return Math.Abs(diferenca);
}

domingo, 1 de fevereiro de 2009

Autenticar / Fazer login / de um usuário da Membership

Autenticar / Fazer login / de um usuário da Membership a partir de seu UserName
if (Membership.ValidateUser(txtUserName.Text, txtPassword.Text))
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true);//Aqui é feito o login

sexta-feira, 30 de janeiro de 2009

Classe List<T>

Alguns dos métodos mais úteis da classe List<T> são:
List<Process> listaProcesso = new List<Process>(Process.GetProcesses());

//retorna somente o primeiro encontrado
Process processo = listaProcesso.Find(delegate(Process p)
   {
   return p.ProcessName.Equals("dllhost");
   });

//retora todos os encontrados
List<Process> listaProcessoContemLetraM = listaProcesso.FindAll(delegate(Process p)
   {
   return p.ProcessName.Contains("m");
   });

//remove todos os encontrados
listaProcesso.RemoveAll(new Predicate<Process>(delegate(Process processoRemover)
   {
   return processoRemover.ProcessName.Equals("dllhost");
   }));

//ordem alfabética
listaProcesso.Sort(new Comparison<Process>( delegate(Process p1, Process p2)
   {
   return p1.ProcessName.CompareTo(p2.ProcessName);
   }));

//existe um pelo menos
Boolean existe = listaProcesso.Exists(delegate(Process p)
   {
   return p.ProcessName.Equals("dllhost");
   });

//existe em todos
Boolean existeTodos = listaProcesso.TrueForAll(delegate(Process p)
   {
   return p.MachineName.Equals(System.Environment.MachineName);
   });

//procura o índice
int indiceProcesso = listaProcesso.FindIndex(delegate(Process p)
   {
   return p.ProcessName.Equals("devenv");
   });

//altera o valor de cada um dos objetos da List
List<String> listaNome = new List<string>();
listaNome.Add("A");
listaNome.Add("B");
listaNome.Add("C");
listaNome.Add("D");

listaNome.ConvertAll<String>(delegate(String n)
   {
   return n.ToLower();
   });

//passar por todos os items da List
listaNome.ForEach(delegate(String n)
   {
   Console.WriteLine(n.ToString());
   });

segunda-feira, 26 de janeiro de 2009

Reflection - Navegando nas propriedades e nos métodos do objeto

Para navegar/identificar as propriedades e métodos de um objeto basta usar reflection.
Essa navegação tem utilidade fazer busca em todas as propriedade do objeto, ou "invocar" todos os métodos do mesmo.

Segue abaixo um exemplo simples de como funciona.
Console.WriteLine("Passando uma a uma das propriedades do objeto");
System.Reflection.PropertyInfo[] colecaoPropriedade = texto.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo propriedade in colecaoPropriedade)
{
Console.WriteLine(propriedade.ToString());
}

Console.WriteLine("Passando um a um dos metodos do objeto");
System.Reflection.MethodInfo [] colecaoMetodo = texto.GetType().GetMethods();
foreach (System.Reflection.MethodInfo metodo in colecaoMetodo)
{
Console.WriteLine(metodo.ToString());
}

sexta-feira, 23 de janeiro de 2009

Select com ordenação aleatória

Considerando que a coluna Codigo é do tipo uniqueidentifier, para uma consulta sql retornar em uma order aleatória basta fazer o seguinte:
SELECT
Codigo,
Nome
FROM
Tabela
ORDER BY NEWID()
Créditos: Jean Charles Bulinckx

Site em manutenção

Para fazer manutenção em seu site e manter uma página amigável indicando a sua manutenção, ou simplismente tirá-lo do ar crie a página App_offline.htm no diretório raíz da aplicação. Assim independente da página que o usuário acessar, entrará nesta página.

Mais informacões aqui e aqui.