Iniezione della logica di elaborazione dati in classe

7

Voglio trovare più elegante e apprezzare il modo di iniettare processori in CommandProcessorDispatcher class. Oppure può essere un'altra soluzione (l'obiettivo è separare ogni logica di elaborazione dei comandi alla classe indipendente). Forse qualche schema di progettazione può essere utile qui. Grazie.

public interface ICommand { }
public class StartCommand : ICommand { }
public class StopCommand : ICommand { }

public interface ICommandProcessor<in T> where T : ICommand
{
    void Process(T command);
}

public class StartCommandProcessor : ICommandProcessor<StartCommand>
{
    public void Process(StartCommand command) { }
}

public class StopCommandProcessor : ICommandProcessor<StopCommand>
{
    public void Process(StopCommand command) { }
}

public interface ICommandProcessorDispatcher
{
    void Process(ICommand command);
}

public class CommandProcessorDispatcher : ICommandProcessorDispatcher
{
    public CommandProcessorDispatcher(Dictionary<Type, Action<ICommand>> processors)
    {
        _processors = processors;
    }

    private readonly Dictionary<Type, Action<ICommand>> _processors;

    public void Process(ICommand command)
    {
        _processors[command.GetType()](command);
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var dict = new Dictionary<Type, Action<ICommand>>
        {
            { typeof(StartCommand), x => new StartCommandProcessor().Process((StartCommand)x) },
            { typeof(StopCommand), x => new StopCommandProcessor().Process((StopCommand)x) },
        };

        var dispatcher= new CommandProcessorDispatcher(dict);
    }
}
    
posta Boo 14.02.2015 - 15:40
fonte

2 risposte

0

Credo che tu possa semplificare un po 'le cose, senza troppo standard, godendo comunque di alcuni sicurezza di tipo.

Un esempio forzato:

public interface ICommand
{
}

#region Friends
public abstract class CommandProcessor
{
    internal abstract void Process(ICommand command);

    public abstract Type CommandType { get; }
}

public abstract class CommandProcessor<TCommand> : CommandProcessor
    where TCommand : ICommand
{
    internal override void Process(ICommand command)
    {
        Process((TCommand)command);
    }

    protected abstract void Process(TCommand command);

    public override Type CommandType { get { return typeof(TCommand); } }
}

public class CommandProcessorDispatcher
{
    public CommandProcessorDispatcher(IEnumerable<CommandProcessor> processors)
    {
        Processors = processors;
    }

    public void Process(ICommand command)
    {
        var found =
            Processors.
            FirstOrDefault
            (
                processor => processor.CommandType == command.GetType()
            );
        if (found == null)
        {
            throw new InvalidOperationException("no suitable processor found");
        }
        found.Process(command);
    }

    // (may just be protected only, depending on requirements)
    public IEnumerable<CommandProcessor> Processors { get; protected set; }
}
#endregion

public class StartCommand : ICommand
{
    public override string ToString()
    {
        return StartId.ToString();
    }

    public int StartId { get; set; }
}

public class StopCommand : ICommand
{
    public override string ToString()
    {
        return StopId.ToString();
    }

    public int StopId { get; set; }
}

public class StartCommandProcessor : CommandProcessor<StartCommand>
{
    protected override void Process(StartCommand command)
    {
        Console.WriteLine("START : " + command);
    }
}

public class EndCommandProcessor : CommandProcessor<StopCommand>
{
    protected override void Process(StopCommand command)
    {
        Console.WriteLine("STOP : " + command);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        var dispatcher =
            new CommandProcessorDispatcher
            (
                new CommandProcessor[]
                {
                    new StartCommandProcessor(),
                    new EndCommandProcessor()
                }
            );

        var start = new StartCommand { StartId = 123 };
        var stop = new StopCommand { StopId = 456 };

        dispatcher.Process(start);
        dispatcher.Process(stop);

        Console.ReadKey();
    }
}

Questo rende meno ipotesi su come i processori di comando sono archiviati, e non richiede delegati di azione, cosa che mi è sfuggita per vedere lo scopo nel tuo esempio - infine, penso che sia preferibile avere il downcast (da ICommand a uno delle sue implementazioni) si verificano solo in una posizione.

    
risposta data 05.10.2016 - 00:30
fonte
-1

Con attenzione su:

[...]or it can be another one solution (the goal is separate each command processing logic to independent class)

l'utilizzo di Factory può semplificare le cose:

public interface ICommand { }
public class StartCommand : ICommand { }
public class StopCommand : ICommand { }

public interface ICommandProcessor
{
    void Process(ICommand command);
}

public class StartCommandProcessor : ICommandProcessor
{
    public void Process(ICommand command) { }
}

public class StopCommandProcessor : ICommandProcessor
{
    public void Process(ICommand command) { }
}

public class UnknownCommandProcessor : ICommandProcessor
{
    public void Process(ICommand command) { }
}

public class CommandProcessorDispatcher
{
    public void Process(ICommand command)
    {
        var processor = CommandProcessorFactory.GetCommandProcessor(command);
        processor.Process(command);
    }
}

public static class CommandProcessorFactory
{
    public static ICommandProcessor GetCommandProcessor(ICommand command)
    {
        if (command is StartCommand)
            return new StartCommandProcessor();
        else if (command is StopCommand)
            return new StopCommandProcessor();
        else
            return new UnknownCommandProcessor();
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var dispatcher = new CommandProcessorDispatcher();            
        dispatcher.Process(new StartCommand());
        dispatcher.Process(new StopCommand());
        Console.ReadLine();
    }
}
    
risposta data 29.04.2018 - 08:40
fonte