저는 클라이언트가 다양한 유형의 명령을 서버에 보내고 구체적인 결과를 얻을 수있는 간단한 클라이언트 - 서버 솔루션을 개발 중입니다. 명령은 다른 특성을 가질 수 있습니다. 내가 원하는 것은 특정 명령 처리기가 처리하는 명령 유형에 따라 선택할 수있는 아키텍처입니다.캐스팅을 더 나은 패턴으로 바꿉니다.
public interface ICommand
{
}
public class CommandA: ICommand
{
public string CustomProperty { get; set; }
}
public class CommandB: ICommand
{
}
각 명령은 명령을 처리하고 결과를 반환 할 책임이 자신의 CommandHandler을 가지고 다음과 같이 나는 기본 인프라를 만들었습니다.
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;
}
}
가 나는 또한 그 결과 적절한 핸들러를 선택하고 반환에 대한 책임 클래스 생성 : 그들은 모두 CommandHandlerBaseClass에서 상속 내가 CommandHandlerBase 클래스에 캐스팅 좋아하지 않는
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);
}
}
을,하지만 난 찾을 수 없습니다 그것을 피할 수있는 모든 패턴. 아래에 표시된 것처럼 일반 인터페이스를 만들 수 있지만 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
};)
그래서 나는 결국 콘크리트 명령으로 직렬화 적합한 핸들러에 의해 처리 될 필요가 문자열을받을 수 있습니다. 그러한 시나리오에서 캐스트를 피할 수있는 방법이 있습니까? IoC 라이브러리로 StructureMap을 사용합니다.
동의. 'Handle (TCommand로서의 명령)'대신'Handle ((TCommand) 명령)'을 말해야합니다. – Timwi
@ SoftwareFactor 필자는 주물과 함께 살 수 있지만 최근에 비슷한 패턴을 여러 번 사용했음을 깨달았고 다른 것으로 대체 될 수 있다면 호기심을 자극했습니다. 그리고 당신은 rigth, 나는이 경우 '로'사용해서는 안됩니다. –