Я надеюсь, что название не вводит в заблуждение, но я не смог найти правильный язык, чтобы определить мою проблему в одном вопросе.
Недавно я пытался реализовать шаблон проектирования "CQRS Command Handler" с использованием C ++. У меня есть 2 иерархии, которые я должен жениться вместе:
ICommand
struct ICommand
{
virtual ~ICommand() = default;
};
struct SampleCommand : ICommand
{
int sampleParameter;
SampleCommand() : sampleParameter(0)
{
}
explicit SampleCommand(const int sampleParameter)
{
this->sampleParameter = sampleParameter;
}
};
ICommandHandler
template<typename T, typename = std::enable_if_t<std::is_base_of<ICommand, std::decay_t<T>>::value>>
struct ICommandHandler
{
virtual void Handle(std::shared_ptr<T> command) = 0;
virtual ~ICommandHandler() = default;
};
class SampleCommandHandler : public ICommandHandler<SampleCommand>
{
public:
void Handle(std::shared_ptr<SampleCommand> command) override
{
std::cout << "sampleParameter " << command->sampleParameter << std::endl;
}
};
Последний кусок, который мне нужно реализовать, - это диспетчер, который принимает команду, находит обработчик и делегирует команду найденному обработчику. Первой идеей, которая пришла мне в голову, было раскрыть некоторый API регистрации обработчиков в диспетчере и написать метод диспетчеризации, который просто попытался бы выполнить динамическую трансляцию всех зарегистрированных обработчиков, и, если какое-то приведение было успешным, он вызвал бы найденный обработчик, как показано ниже:
class Dispatcher
{
public:
template<typename T>
void Dispatch(std::shared_ptr<T> command)
{
auto handler = std::find_if(std::begin(_handlers), std::end(_handlers), [](auto handler)
{
return dynamic_cast<ICommandHandler<T>*>(handler);
});
if(handler != std::end(_handlers))
{
(*handler)->Handle(command);
}
}
private:
std::vector<?> _handlers;
};
Вопрос в том, какого типа должно быть хранилище "_handlers" std :: vector, чтобы метод Dispatcher :: Dispatch работал нормально и возможно ли это?
Что я пробовал до сих пор:
std :: vector - не скомпилирован, поскольку приведение конкретного обработчика к ICommandHandler *> невозможно.
Error C2440 'initializing': cannot convert from 'SampleCommandHandler *' to 'ICommandHandler<ICommand,void> *'
std :: vector - не скомпилирован, так как dynamic_cast нельзя применить к void *