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 😉