Faz algum tempo que procuro um meio de executar códigos antes e depois da execução de um método, de forma limpa. Estava procurando isto especificamente por causa desde tipo de código:
public void MyMethod()
{
BeginTransaction();
try
{
[meu código para executar no DB]
CommitTransaction();
}
catch (Exception)
{
RollbackTransaction();
throw;
}
}
Este código é complexo de entender, e suja muito os métodos, principalmente se eu tiver que repeti-lo diversas vezes. Além disso, corre o risco, como já aconteceu, de eu esquecer de colocar alguma parte dele (por exemplo, o CommitTransaction).
Procurei um meio de colocar apenas um Attribute acima do método, e ele entender que quero cercar o método com o meu código. Descobri que é necessário mexer com um nível mais baixo, e até há uma biblioteca (paga) que posso baixar para fazer isso por mim.
Mas encontrei uma sugestão que, apesar de não ser tão limpa quanto colocar um Attribute, deixa o código simples e é como se você criasse um bloco de execução seu: http://stackoverflow.com/questions/6046382/suggestions-for-making-a-reusable-try-catch-block-in-c
Seguindo o exemplo, meu código acima ficaria assim:
public void MyMethod()
{
InTransaction(() =>
{
[meu código para executar no DB]
});
}
protected void InTransaction(Action action)
{
BeginTransaction();
try
{
action();
CommitTransaction();
}
catch (Exception)
{
RollbackTransaction();
throw;
}
}
Assim todos os métodos que forem usar transaction apenas precisarão ser colocados dentro desse bloco novo. Se for necessário retornar valor, a mudança nesse código seria esta:
public T MyMethod()
{
return InTransaction(() =>
{
return [meu código para executar no DB]
});
}
protected T InTransaction<T>(Func<T> action)
{
BeginTransaction();
try
{
var result = action();
CommitTransaction();
return result;
}
catch (Exception)
{
RollbackTransaction();
throw;
}
}
Assim é possível encurtar o código e diminuir os erros que podem ser cometidos ao programar.