Processor for handling generic commands

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












I'm trying to implement business logic layer based on concepts of commands and command handlers.



A command is a thing that contains input parameters for executing some action, and it knows what kind of output that action should produce. A command handler contains logic for actually executing an action: it accepts a command as a param, handles it in some way, and (if successful) produces an output object.



public interface ICommand<TResultData>


public interface ICommandHandler<TCommand, TResultData>
where TCommand : ICommand<TResultData>

CommandResult<TResultData> Handle(TCommand command);


public static class CommandProcessor

public static CommandResult<TResultData> Process<TCommand, TResultData>(TCommand command)
where TCommand : ICommand<TResultData>

var handler = ServiceLocator.GetInstance<ICommandHandler<TCommand, TResultData>>();
return handler.Handle(command);


public class CommandResult<TResultData>

public bool Success get; set;

public string Error get; set;

public TResultData Data get; set;



Example usage:



// CreateUserCommand & handler implementations *very* simplified
public class CreateUserCommand : ICommand<User>

public string Email get; set;


public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, User>

private readonly IRepository repository;
public CreateUserCommandHandler (IRepository repository)

this.repository = repository;

public CommandResult<User> Handle(CreateUserCommand command)

if(this.repository.Users.Any(u=>u.Email == command.Email)
return new CommandResult<User> Success = false, Error = "Email already taken";
var user = new User Email = command.Email;
this.repository.Users.Add(user);
return new CommandResult<User> Success = true, Data = user;



// command usage in application code
var command = new CreateUserCommand Email = "some.email.com" ;
CommandResult<User> result = CommandProcessor.Process(command);
if(result.Success)

// at this point we know that result.Data is of type User, which is nice
// so we can use this strictly-typed result data in any way
User createdUser = result.Data;
Console.Writeline("Created user with Id = " + createdUser.Id);

else

Console.Writeline("Error creating user: " + result.Error);



Everything works pretty nice, as you can see in the usage example, but one thing that bothers me is the empty interface ICommand. Is it a bad thing here? Can the code be refactored in some way to make it better?







share|improve this question





















  • Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
    – t3chb0t
    Feb 23 at 20:29










  • @t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
    – Andre Borges
    Feb 23 at 20:50










  • Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
    – t3chb0t
    Feb 23 at 21:10










  • Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
    – Andre Borges
    Feb 23 at 21:35










  • I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
    – julealgon
    Jun 15 at 21:58
















up vote
2
down vote

favorite












I'm trying to implement business logic layer based on concepts of commands and command handlers.



A command is a thing that contains input parameters for executing some action, and it knows what kind of output that action should produce. A command handler contains logic for actually executing an action: it accepts a command as a param, handles it in some way, and (if successful) produces an output object.



public interface ICommand<TResultData>


public interface ICommandHandler<TCommand, TResultData>
where TCommand : ICommand<TResultData>

CommandResult<TResultData> Handle(TCommand command);


public static class CommandProcessor

public static CommandResult<TResultData> Process<TCommand, TResultData>(TCommand command)
where TCommand : ICommand<TResultData>

var handler = ServiceLocator.GetInstance<ICommandHandler<TCommand, TResultData>>();
return handler.Handle(command);


public class CommandResult<TResultData>

public bool Success get; set;

public string Error get; set;

public TResultData Data get; set;



Example usage:



// CreateUserCommand & handler implementations *very* simplified
public class CreateUserCommand : ICommand<User>

public string Email get; set;


public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, User>

private readonly IRepository repository;
public CreateUserCommandHandler (IRepository repository)

this.repository = repository;

public CommandResult<User> Handle(CreateUserCommand command)

if(this.repository.Users.Any(u=>u.Email == command.Email)
return new CommandResult<User> Success = false, Error = "Email already taken";
var user = new User Email = command.Email;
this.repository.Users.Add(user);
return new CommandResult<User> Success = true, Data = user;



// command usage in application code
var command = new CreateUserCommand Email = "some.email.com" ;
CommandResult<User> result = CommandProcessor.Process(command);
if(result.Success)

// at this point we know that result.Data is of type User, which is nice
// so we can use this strictly-typed result data in any way
User createdUser = result.Data;
Console.Writeline("Created user with Id = " + createdUser.Id);

else

Console.Writeline("Error creating user: " + result.Error);



Everything works pretty nice, as you can see in the usage example, but one thing that bothers me is the empty interface ICommand. Is it a bad thing here? Can the code be refactored in some way to make it better?







share|improve this question





















  • Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
    – t3chb0t
    Feb 23 at 20:29










  • @t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
    – Andre Borges
    Feb 23 at 20:50










  • Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
    – t3chb0t
    Feb 23 at 21:10










  • Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
    – Andre Borges
    Feb 23 at 21:35










  • I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
    – julealgon
    Jun 15 at 21:58












up vote
2
down vote

favorite









up vote
2
down vote

favorite











I'm trying to implement business logic layer based on concepts of commands and command handlers.



A command is a thing that contains input parameters for executing some action, and it knows what kind of output that action should produce. A command handler contains logic for actually executing an action: it accepts a command as a param, handles it in some way, and (if successful) produces an output object.



public interface ICommand<TResultData>


public interface ICommandHandler<TCommand, TResultData>
where TCommand : ICommand<TResultData>

CommandResult<TResultData> Handle(TCommand command);


public static class CommandProcessor

public static CommandResult<TResultData> Process<TCommand, TResultData>(TCommand command)
where TCommand : ICommand<TResultData>

var handler = ServiceLocator.GetInstance<ICommandHandler<TCommand, TResultData>>();
return handler.Handle(command);


public class CommandResult<TResultData>

public bool Success get; set;

public string Error get; set;

public TResultData Data get; set;



Example usage:



// CreateUserCommand & handler implementations *very* simplified
public class CreateUserCommand : ICommand<User>

public string Email get; set;


public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, User>

private readonly IRepository repository;
public CreateUserCommandHandler (IRepository repository)

this.repository = repository;

public CommandResult<User> Handle(CreateUserCommand command)

if(this.repository.Users.Any(u=>u.Email == command.Email)
return new CommandResult<User> Success = false, Error = "Email already taken";
var user = new User Email = command.Email;
this.repository.Users.Add(user);
return new CommandResult<User> Success = true, Data = user;



// command usage in application code
var command = new CreateUserCommand Email = "some.email.com" ;
CommandResult<User> result = CommandProcessor.Process(command);
if(result.Success)

// at this point we know that result.Data is of type User, which is nice
// so we can use this strictly-typed result data in any way
User createdUser = result.Data;
Console.Writeline("Created user with Id = " + createdUser.Id);

else

Console.Writeline("Error creating user: " + result.Error);



Everything works pretty nice, as you can see in the usage example, but one thing that bothers me is the empty interface ICommand. Is it a bad thing here? Can the code be refactored in some way to make it better?







share|improve this question













I'm trying to implement business logic layer based on concepts of commands and command handlers.



A command is a thing that contains input parameters for executing some action, and it knows what kind of output that action should produce. A command handler contains logic for actually executing an action: it accepts a command as a param, handles it in some way, and (if successful) produces an output object.



public interface ICommand<TResultData>


public interface ICommandHandler<TCommand, TResultData>
where TCommand : ICommand<TResultData>

CommandResult<TResultData> Handle(TCommand command);


public static class CommandProcessor

public static CommandResult<TResultData> Process<TCommand, TResultData>(TCommand command)
where TCommand : ICommand<TResultData>

var handler = ServiceLocator.GetInstance<ICommandHandler<TCommand, TResultData>>();
return handler.Handle(command);


public class CommandResult<TResultData>

public bool Success get; set;

public string Error get; set;

public TResultData Data get; set;



Example usage:



// CreateUserCommand & handler implementations *very* simplified
public class CreateUserCommand : ICommand<User>

public string Email get; set;


public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, User>

private readonly IRepository repository;
public CreateUserCommandHandler (IRepository repository)

this.repository = repository;

public CommandResult<User> Handle(CreateUserCommand command)

if(this.repository.Users.Any(u=>u.Email == command.Email)
return new CommandResult<User> Success = false, Error = "Email already taken";
var user = new User Email = command.Email;
this.repository.Users.Add(user);
return new CommandResult<User> Success = true, Data = user;



// command usage in application code
var command = new CreateUserCommand Email = "some.email.com" ;
CommandResult<User> result = CommandProcessor.Process(command);
if(result.Success)

// at this point we know that result.Data is of type User, which is nice
// so we can use this strictly-typed result data in any way
User createdUser = result.Data;
Console.Writeline("Created user with Id = " + createdUser.Id);

else

Console.Writeline("Error creating user: " + result.Error);



Everything works pretty nice, as you can see in the usage example, but one thing that bothers me is the empty interface ICommand. Is it a bad thing here? Can the code be refactored in some way to make it better?









share|improve this question












share|improve this question




share|improve this question








edited Feb 23 at 20:47
























asked Feb 23 at 19:27









Andre Borges

1755




1755











  • Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
    – t3chb0t
    Feb 23 at 20:29










  • @t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
    – Andre Borges
    Feb 23 at 20:50










  • Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
    – t3chb0t
    Feb 23 at 21:10










  • Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
    – Andre Borges
    Feb 23 at 21:35










  • I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
    – julealgon
    Jun 15 at 21:58
















  • Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
    – t3chb0t
    Feb 23 at 20:29










  • @t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
    – Andre Borges
    Feb 23 at 20:50










  • Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
    – t3chb0t
    Feb 23 at 21:10










  • Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
    – Andre Borges
    Feb 23 at 21:35










  • I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
    – julealgon
    Jun 15 at 21:58















Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
– t3chb0t
Feb 23 at 20:29




Could you add the implementation for CreateUserCommand? Regarding your question about the ICommand interface: why does it not have this API CommandResult<TResultData> Handle(TCommand command);? It's more natural to have it there than on a separate ICommandHandler. It'd be also nice if ou could add its implementation too.
– t3chb0t
Feb 23 at 20:29












@t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
– Andre Borges
Feb 23 at 20:50




@t3chb0t, I added command implementation. Command doesn't have Handle method because I want to separate input data from the logic that processes it (to be possible to inject data into handlers using DI, like IRepository in the example, or to have multiple handlers for one command)
– Andre Borges
Feb 23 at 20:50












Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
– t3chb0t
Feb 23 at 21:10




Multiple handlers for one command? This doesn't sound like a good idea. Your command is more like a command-parameter and the actual command is the handler.
– t3chb0t
Feb 23 at 21:10












Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
– Andre Borges
Feb 23 at 21:35




Well, I'm not gonna argue for/against multiple handlers (anyway, it's not implemented in my code as you can see) as it's a controversial subject indeed. But there are other reasons for separating data & logic: constructor DI possibility in handlers, avoiding fat classes (there may me dozens of props in commands and several methods in complicated handlers), etc.
– Andre Borges
Feb 23 at 21:35












I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
– julealgon
Jun 15 at 21:58




I'm trying to use something very similar but I get a compilation error on the .Process call, telling me the compiler cannot infer the type from usage. I have to pass both the command interface and the type of the return value for it to work, which obviously is less than ideal. Any tips? Your code as-is doesn't compile for me.
– julealgon
Jun 15 at 21:58















active

oldest

votes











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188218%2fprocessor-for-handling-generic-commands%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes










 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188218%2fprocessor-for-handling-generic-commands%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation