Как вариант, можно вынести только проверку в отдельный сервис в доменном слое (Domain Layer), и этот сервис передавать как аргумент в метод add() вашей сущности. Если этот сервис бросит исключение, то метод add прекращает выполнение. В сервис передавать в конструкторе репозиторий или другой объект, который подгрузит необходимые для проверки данные.
Далее вынести вызов метода add() в сервис на уровне приложения (Application Layer), как вы написали, в котором и передавать ранее созданный сервис проверки в метод add().
В такой реализации вам всегда будет необходим этот доменный сервис, и вызвать метод add() без него не получится.
Пример:
class Entity
{
public function add(ComplexEntityValidator $validator) {
$validator->validate();
}
}
class ComplexEntityValidator
{
public function __construct(EntityRepository $repository) {
}
public function validate() {
// проверка
}
}
class EntityApplicationService
{
public function __construct(ComplexEntityValidator $validator) {
}
public function __invoke() {
$entity = new Entity();
$entity->add($validator);
// сохранение сущности
}
}