2012-01-14 13 views
8

Actualmente estoy intentando implementar el patrón Transaction Script (Exactamente cómo Martin Fowler described usando Command Pattern) en un proyecto de prueba simple, todo funciona bien, el problema es donde no lo hago saber cómo obtener resultados cuando el método especificado se ejecuta en una clase concreta que se hereda de la interfaz ICommand.Obtener el resultado del método ejecutado en Command Pattern

Vamos a mostrar un código para aclarar qué funcionalidad tengo. tengo una clase CalculateSalaryCommand simple que heredó de interfaz ICommand

public class CalculateSalaryCommand : ICommand 
{ 
    private readonly CalculateSalaryTS _salaryTs; 
    private readonly int _hour; 
    private readonly int _salaryPerHour; 

    public CalculateSalaryCommand(CalculateSalaryTS salaryTs, int hour, int salaryPerHour) 
    { 
     _salaryTs = salaryTs; 
     _hour = hour; 
     _salaryPerHour = salaryPerHour; 
    } 

    public void Execute() 
    { 
     _salaryTs.CalculateSalary(_hour, _salaryPerHour); 
    } 
} 

y una sencilla clase de secuencias de comandos de transacción CalculateSalaryTS nombrados

public class CalculateSalaryTS { 
    public void CalculateSalary(int _hour, int _salaryPerHour) { 
     Result = _hour * _salaryPerHour; 
    } 
} 

como se puede ver paso la instancia de la clase concreta de comandos, a continuación, dentro del método Execute ejecuto operaciones desde esa instancia. Bueno, todo se ve bien. pero hay un problema. No puedo devolver el resultado del método ejecutado, que debe ser un número entero. Para hacer frente a este problema, he decidido añadir algo de código para la capa de transacción script que cada transacción debe heredar de una interfaz genérica ITransactionResult, que es parezca siguiente:

public interface ITransactionResult<TResult> 
{ 
    TResult Result { get; set; } 
} 

Entonces clase CalculateSalaryTS se convirtió de esta manera:

public class CalculateSalaryTS : ITransactionResult<Int32> { 

    public void CalculateSalary(int _hour, int _salaryPerHour) { 
     Result = _hour * _salaryPerHour; 
    } 

    public int Result { get; set; } 

} 

Uso:

var script = new CalculateSalaryTS(); 
    var command = new CalculateSalaryCommand(script, 10, 20);   
    command.Execute(); 
    Console.WriteLine("Salary is {0}", script.Result); 

Sé que esta manera tiene su propia limitación, pero no tengo otra opción hasta que me dé otra idea para manejar esta situación.

Gracias de antemano.

Respuesta

18

Si es absolutamente necesario para obtener el resultado inmediatamente después de la ejecución del comando, se puede almacenar el resultado en el objeto de comando: Método

public interface ICommandWithResult<T> : ICommand 
{ 
    T Result { get; } 
} 

public class CalculateSalaryCommand : ICommandWithResult<int> 
{ 
    public int Result { get; private set; } 

    // ... 

    public void Execute() 
    { 
    _salaryTs.CalculateSalary(_hour, _salaryPerHour); 
    this.Result = _salaryTs.Result; 
    } 
} 

// Usage: 

var command = new CalculateSalaryCommand(new CalculateSalaryTS(), 10, 20); 
command.Execute(); 
Console.WriteLine("Salary is {0}", command.Result); 
+0

Dennis gracias por su respuesta. Usted prefirió una gran solución. Pero dado que soy nuevo en el diseño de conceptos de patrones, me confundo sobre agregar funcionalidad adicional al comportamiento de 'ICommand'. ¿Es correcto? – saber

+2

No creo que haya un problema para extender tus comandos según sea necesario. Los Patrones de diseño son una guía para resolver problemas específicos y recurrentes. No están escritos en piedra, sino que son una base sobre la que puedes construir. En su caso específico, ni siquiera necesita agregar la interfaz 'ICommandWithResult '. Simplemente puede imponer 'ICommand' para agregar la propiedad' Result' al 'CalculateSalaryClass'. –

+0

+1 gracias Dennis. – saber

4

Creo que está buscando un patrón de comando que sea capaz de devolver resultados.

así,

interface ICommand<TResult> 
    { 
     TResult Execute(); 
    } 


public class CalculateSalaryCommand : ICommand<int> 
{ 
    private readonly CalculateSalaryTS _salaryTs; 
    private readonly int _hour; 
    private readonly int _salaryPerHour; 

    public CalculateSalaryCommand(CalculateSalaryTS salaryTs, int hour, int salaryPerHour) 
    { 
     _salaryTs = salaryTs; 
     _hour = hour; 
     _salaryPerHour = salaryPerHour; 
    } 

    public int Execute() 
    { 
     return _salaryTs.CalculateSalary(_hour, _salaryPerHour); 
    } 
} 
+2

Comando del patrón debe ser nula, vamos imagina que tienes razón, ¿qué tal si quiero ejecutar un método que es nulo? que debería hacer ? – saber

+0

@SaberAmani: De dos maneras, implemente ICommand que devuelve nulo o tiene un método/propiedad llamado 'GetResult()'. – Spoike

Cuestiones relacionadas