Esses dias estive recapitulando algumas partes do livro Writing Secure Code – Second Edition e achei muito interessante (e engraçacado :)) o significado que os autores deram para o método Assert da classe CodeAccessPermission: “[…] In essence, Assert means, “I know what I’m doing; trust me.” […]”. 🙂
Arquivo da categoria: .NET Framework
Retorno de DataReaders – Solução Elegante
Todos sabemos que retornar DataReaders através de funções é um tanto quanto perigoso, pois o DataReader exige uma conexão ativa com a base de dados e delega ao consumidor do método fechar a conexão com o mesmo explicitamente. Apesar de perigoso, há um cenário onde retornar DataReaders é muito comum, ou seja, quando estavamos desenvolvendo uma DAL, um dos principais métodos é o ExecuteReader, a menos que voce somente trabalhe com Datasets 😛
Keith Brown dá uma solução muito elegante para continuar retornando DataReaders através de funções, porém a responsabilidade em fechar o mesmo, fica dentro da própria classe, evitando assim que o DataReader fique aberto, prejudicando a aplicação. A solução é a utilização de um delegate que, em sua assinatura, recebe um parametro do tipo XXXDataReader. Se estivermos consumindo a classe a partir do C#, podemos optar por utilizar um método anonimo para as coisas ficarem ainda mais bonitas:
DalHelper dal = new DalHelper(Util.Settings.DbConnectionString);
dal.ExecuteSecureReader(“SELECT Nome FROM Clientes”, CommandType.Text,
delegate(DbDataReader dr)
{
while (dr.Read())
{
Response.Write(dr.GetString(0));
}
});
Se o consumo da classe for no VB.NET, voce consegue ter todos os beneficios com relação ao fechamento da conexão, mas precisará criar uma função a parte para tratar o resultado. Com certeza, o benefício vale mais do que 3 ou 4 linhas de código a mais. 😉
DateTime
Alguém faz idéia de que existe boas práticas para trabalhar com a estrutura DateTime?
Encoder Fallbacks
Quando utilizamos algum codificador que não consegue codificar ou decodificar algum caracter, ele coloca um ponto de interrogação “?” para indicar que o codificador corrente não é capaz de “traduzí-lo”.
A classe Encoding fornece dois métodos chamados GetEncoder e GetDecoder, que retornam os objetos responsáveis por codificar e decodificar as strings, respectivamente. Ambas as classes possuem uma propriedade chamada FallBack. Essa propriedade recebe um objeto do tipo EncoderFallback ou DecoderFallback que representam uma ação que será executada quando um caracter ou um byte não puder ser convertido.
As classes EncoderFallback e DecoderFallback são utilizadas na codificação e decodificação, respectivamente. A primeira delas é a classe base para todos os fallbacks de codificação e, a segunda, a classe base para todos os fallbacks de decodificação. Basicamente, para ambos os casos, temos dois tipos de fallbacks:
- Fallbacks de Substituição: Quando um caracter ou byte não consegue ser “traduzido”, ele substitui o mesmo por um caracter que podemos determinar. Por padrão, o ponto de interrogação “?” é utilizado.
- EncoderReplacementFallback: Fallback que é invocado quando um caracter que puder ser convertido em uma seqüencia de bytes, convertendo o caracter para um valor pré-definido.
- DecoderReplacementFallback: Fallback que é invocado quando uma seqüencia de bytes não puder ser convertida em um caracter, convertendo o byte para um valor pré-definido.
- Fallbacks de Excessões: Quando um caracter ou byte não consegue ser “traduzido”, ele atira uma excessão do tipo EncoderFallbackException ou DecoderFallbackException, dependendo da operação que estamos tentando realizar.
- EncoderExceptionFallback: Fallback que é invocado quando um caracter que puder ser convertido em uma seqüencia de bytes, atirando uma excessão do tipo EncoderFallbackException.
- DecoderExceptionFallback: Fallback que é invocado quando uma seqüencia de bytes não puder ser convertida em um caracter, atirando uma excessão do tipo DecoderFallbackException.
O código abaixo exemplifica a utilização de um dos fallbacks acima:
using System.Text;
//….
Encoder encoder = Encoding.ASCII.GetEncoder();
encoder.Fallback = new EncoderReplacementFallback(“*”);
char[] chars = “ãBC”.ToCharArray();
Byte[] buffer = new byte[chars.Length];
encoder.GetBytes(chars, 0, chars.Length, buffer, 0, true);
Console.WriteLine(Encoding.ASCII.GetString(buffer));
O resultado ao executar esse código é: *BC. O “ã” é substituído pelo “*” porque esse caracter não está contemplado no padrão ASCII e, conseqüentemente, não consegue ser “traduzido”. A utilização dos fallbacks são muito úteis quando voce quer customizar a leitura ou gravação de streams. A utilização de fallbacks de excessões são as vezes mais utilizadas quando a leitura dos caracteres devem ser precisa.
Pool de Objetos
Na empresa onde trabalho, desenvolvemos alguns objetos que são muito custosos durante a sua criação. São checagens, a nível de segurança e também a dados dentro de um determinado banco de dados. Quando inciamos a fase de testes, notamos que o construtor e alguns trabalhos que fazemos durante os métodos e propriedades estava levando muito tempo para serem executados e, na maioria das vezes, eles fazem sempre as mesmas validações.
Para contornar a situação, optamos por implementar uma espécie de pool de objetos. Depois de muito ler e efetuarmos testes, chegamos a uma forma que, até então, parece-me trabalhar bem. Essa técnica trata-se da criação de um membro privado estático, do tipo Stack<T> que será o responsável por armazenar os objetos dentro do pool. Logo depois da criação, via construtor, o objeto é automaticamente adicionado a Stack. Como não poderia deixar de ser, mais dois métodos estáticos forem criados: um para extrair o objeto do pool e outro para finalizar o pool, caso não precisar mais dele na aplicação. Além disso, optamos também por criar uma propriedade que irá determinar se aquele objeto deve ou não ser armazenado no pool ou se deve ser descartado diretamente.
public class Order
{
private static Stack<Order> _orderPool = new Stack<Order>();
public Order()
{
_orderPool.Push(this);
}
public static Order GetOrderFromPool()
{
return _orderPool.Pop();
}
public static void ClosePool()
{
_orderPool = null;
}
protected virtual bool CanBePooled
{
get
{
return true;
}
}
~Order()
{
if (_orderPool != null && this.CanBePooled)
{
GC.ReRegisterForFinalize(this);
_orderPool.Push(this);
}
}
}
O único código que merece um comentário adicional é com relação ao destrutor da classe Order. Dentro dele verificamos se o pool não está nulo (isso quer dizer que a aplicação não precisa mais dele) e, além disso, a propriedade CanBePooled deve estar definida como True, o que indica que o objeto pode ser adicionado ao pool. Se essas condições forem atendidas, chamamos o método ReRegisterForFinalize da classe GC, passando a instancia corrente da classe para que o mesma seja ressucitada e, como podemos notar, a instancia é devolvida para o pool via método Push. Thanks JeffreyR 😉
Exibindo propriedades de uma Message
Mensagens que são postadas dentro de uma fila no Microsoft Message Queue podem ser recuperadas retirando-as da fila ou apenas lendo as mesmas, sem remove-las. Essas mensagens são recuperadas e retornam para cada uma delas um objeto do tipo Message.
Esse tipo contém uma porção de propriedades interessantes que podem ser utilizadas na aplicação. Só que, por padrão, várias dessas propriedades não são retornadas e, quando voce tenta acessá-las, uma Exception do tipo InvalidOperationException é atirada. Um exemplo de uma propriedade que não é recupera é a propriedade SentTime, que é a hora de envio da mensagem a fila.
Para recuperarmos uma determinada propriedade, podemos utilizar a propriedade MessageReadPropertyFilter que é responsável por gerenciar qual propriedade será retornada. Há duas formas de fazer isso, ou seja, habilitar exclusivamente apenas uma propriedade ou todas de uma única fez, e as formas são mostradas respectivamente à seguir:
string path = @”.Private$TempQueue”;
MessageQueue queue = new MessageQueue(path);
[ Apenas uma propriedade específica ]
queue.MessageReadPropertyFilter.SentTime = true;
[ Todas as propriedades ]
queue.MessageReadPropertyFilter.SetAll();
Diferenças entre WPF e XBAP
Eis aqui uma lista muito interessante com as diferenças entre WPF e XBAP.
Formatando objetos utilizando IFormattable
Para o nosso cenário de exemplo, teremos dois objetos: Cliente e Cnpj. Cada cliente obrigatoriamente terá uma propriedade do tipo Cnpj. Este tipo por sua vez, implementará a interface IFormattable e deverá fornecer dois tipos de formatação: DF e PR. O primeiro significa “Documento Formatado” e retornará o valor do CNPJ formatado; já a segunda opção significa “PRefixo” e, se o usuário optar por este tipo de formatação, será retornado apenas o prefixo do CNPJ que, para quem não sabe, trata-se dos 9 primeiros dígitos. Vamos então montar a nossa arquitetura de classes que utilizaremos como exemplo:
public class Cliente
{
private string _nome;
private Cnpj _cnpj;
public Cliente(string nome, string cnpj)
{
this._nome = nome;
this._cnpj = new Cnpj(cnpj);
}
public string Nome
{
get
{
return this._nome;
}
set
{
this._nome = value;
}
}
public Cnpj Cnpj
{
get
{
return this._cnpj;
}
set
{
this._cnpj = value;
}
}
}
public class Cnpj : IFormattable
{
private string _numero;
public Cnpj(string numero)
{
this._numero = numero;
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == "DF")
return
Convert.ToDouble(this._numero).ToString(@"000.000.000/0000-00");
else if (format == "PR")
return
Convert.ToDouble(this._numero.Substring(0, 9)).ToString(@"000.000.000");
return this._numero;
}
public override string ToString()
{
return this.ToString(null, null);
}
}
|
Como podemos reparar, a classe Cliente tem uma propriedade chamada Cnpj do tipo Cnpj. O objeto Cnpj implementa a interface IFormattable e, dentro do método ToString, verifica qual o formato está sendo passado para ele. Baseando-se neste formato é que uma determinada formatação é aplicada ao número do CNPJ e, caso nenhuma formatação é especificada, somente o número é retornado, sem nenhuma espécie de formatação. Esse tipo de código nos permitirá fazer algo do tipo:
Cnpj c = new Cnpj("999999999999999");
Response.Write(string.Format("O documento formatado é {0:DF}.", c));
Response.Write(string.Format("O prefixo é {0:PR}.", c));
Response.Write(string.Format("O documento é {0}.", c));
// Output:
// O documento formatado é 999.999.999/9999-99.
// O prefixo é 999.999.999.
// O documento é 999999999999999.
|
Esse tipo de formatação torna tudo muito flexível e, podemos ainda especificar o tipo de formatação em controles DataBound, como por exemplo o GridView do ASP.NET, da mesma forma que fazemos para datas e números. As imagens abaixo ilustram isso:
|
|
|
| Figura 1 – Configuração da formatação no GridView. | |
Novo WTF!
Eu encontrei um novo WTF:
try
{
using (cnn)
{
cnn.Open();
cmd.ExecuteNonQuery();
}
}
finally
{
cnn.Close();
}
Eu acredito que não preciso explicar porque o código acima é considerado um WTF, ou preciso?
WTF!
Um típico WTF 🙂
Public Sub New(ByVal str As String)
If (str = String.Empty Or str = Nothing Or String.IsNullOrEmpty(str) Or Len(str) = 0) Then
str = “”
End If
Me._str = str
End Sub
