我正致力于简单的客户端 - 服务器解决方案,客户端可以向服务器发送不同类型的命令并获得特定结果。命令可以具有不同的属性。我想要的是一种架构,可以根据它处理的命令类型选择特定的命令处理程序。我创建了基本的基础架构如下:
public interface ICommand
{
}
public class CommandA: ICommand
{
public string CustomProperty { get; set; }
}
public class CommandB: ICommand
{
}
每个命令都有自己的CommandHandler,负责处理命令和返回结果。它们都继承自CommandHandlerBaseClass:
public interface ICommandHandler
{
bool CanHandle(ICommand command);
IReply Handle(ICommand command);
}
public abstract class CommandHandlerBase<TCommand> : ICommandHandler
where TCommand : class, ICommand
{
public bool CanHandle(ICommand command)
{
return command is TCommand;
}
public IReply Handle(ICommand command)
{
return Handle(command as TCommand);
}
public abstract IReply Handle(TCommand command);
}
// Specific handler
public class CommandAHandler : CommandHandlerBase<CommandA>
{
public override IReply Handle(CommandA command)
{
//handling command and returning result
return null;
}
}
我还创建了一个负责选择合适的处理程序并返回结果的类:
public interface IReplyCreator
{
IReply GetReply(ICommand command);
}
public class ReplyCreator : IReplyCreator
{
private readonly IEnumerable<ICommandHandler> _commandHandlers;
public ReplyCreator(IEnumerable<ICommandHandler> commandHandlers)
{
_commandHandlers = commandHandlers;
}
public IReply GetReply(ICommand command)
{
var commandHandler = _commandHandlers
.FirstOrDefault(x => x.CanHandle(command));
if (commandHandler == null)
return null;
return commandHandler.Handle(command);
}
}
我不喜欢在CommandHandlerBase类中进行转换,但是我找不到任何模式来避免它。我可以创建一个如下所示的通用接口,但是如何在ReplyCreator中注册并选择一个特定的处理程序呢?
public interface ICommandHandler<TCommand>
where TCommand : ICommand
{
bool CanHandle(TCommand command);
IReply Handle(TCommand command);
}
服务器中收到的命令使用Json.net序列化,如下所示:
JsonConvert.SerializeObject(new CommandA(), new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};)
所以我收到一个字符串,最终需要反序列化为具体的命令并由合适的处理程序处理。在这种情况下,有没有办法避免演员阵容?我使用StructureMap作为我的IoC库。
答案 0 :(得分:3)
你为什么试图避免这种演员?现在我想到的任何变通方法都不会比这更好。
我会避免使用as
关键字来实现此目的。当错误的类型传递给处理程序时,它将在不太可能的情况下无声地失败。在这种情况下,您希望立即抛出异常,而不是在代码中的某个地方抛出异常。