En mi proyecto actual estoy usando clases que implementan la siguiente interfaz ITransaction
que se muestra a continuación. Esta es una interfaz genérica para una transacción que se puede deshacer. También tengo una clase TransactionSet
que se utiliza para intentar varias Transacciones o conjuntos de transacciones, y en última instancia se puede usar para crear un árbol de transacciones.¿Está bien disparar eventos desde Dispose()?
Algunas implementaciones de ITransaction
mantienen referencias temporales a instancias de objetos o archivos que pueden usar más adelante si hay una llamada al Undo()
. Posteriormente se puede confirmar una transacción exitosa después de lo cual ya no se permite Undo()
y, por lo tanto, ya no es necesario contar con los datos temporales. Actualmente estoy usando Dispose()
como mi método de confirmación para limpiar cualquier recurso temporal.
Sin embargo, ahora me gustaría que mis transacciones también activen eventos para notificar a otras clases de lo que ha sucedido. No quiero que los eventos se activen a menos que se confirme la transacción. Porque no quiero permitir que una transacción active eventos varias veces al deshacerse y luego volver a ejecutar.
Dado que estoy usando Dispose()
para confirmar una transacción, ¿hay algún problema con disparar también estos eventos desde ella? ¿O sería mejor tener un método separado Confirm()
en mi interfaz que dispara los eventos además de Dispose()
que limpia los datos temporales? No puedo pensar en ningún caso en el que me gustaría confirmar, pero no disponer de una transacción. Sin embargo, no está del todo claro para mí lo que debería y no debo hacer dentro de Dispose()
.
public enum TransactionStatus
{
NotRun, // the Transaction has not been run, or has been undoed back to the original state
Successful, ///the action has been run and was successful
Error //there was an attempt to run the action but it failed
}
/// <summary>
/// Generic transaction interface
/// </summary>
public interface ITransaction
{
TransactionStatus Status { get; }
/// <summary>
/// Attempts the transaction returns true if successful, false if failed.
/// If failed it is expected that everything will be returned to the original state.
/// Does nothing if status is already Successful
/// </summary>
/// <returns></returns>
bool Go();
/// <summary>
/// Reverts the transaction
/// Only does something if status is successful.
/// Should return status to NotRun
/// </summary>
void Undo();
/// <summary>
/// A message describing the cause of the error if Status == Error
/// Otherwise equal String.Empty
/// </summary>
string ErrorMessage { get; }
}
Varias clases .net tienen un evento "Disposing" y serían muy difíciles de usar sin una. Si un objeto contiene una referencia a un IDisposable que puede usarse o no en otro lugar (por ejemplo, un Control que contiene una Imagen de Fondo), se puede usar un evento de Eliminación para permitir que el titular del objeto principal limpie el objeto anidado cuando sea necesario. – supercat