diff --git a/src/Plugin/Field/FieldType/DynamicEntityReferenceFieldItemList.php b/src/Plugin/Field/FieldType/DynamicEntityReferenceFieldItemList.php
index da49c9d..6649c99 100644
--- a/src/Plugin/Field/FieldType/DynamicEntityReferenceFieldItemList.php
+++ b/src/Plugin/Field/FieldType/DynamicEntityReferenceFieldItemList.php
@@ -6,6 +6,7 @@ use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Entity\Plugin\Validation\Constraint\ValidReferenceConstraint;
 use Drupal\Core\Field\EntityReferenceFieldItemList;
 use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemList;
 use Drupal\Core\Form\FormStateInterface;
 
 /**
@@ -30,6 +31,7 @@ class DynamicEntityReferenceFieldItemList extends EntityReferenceFieldItemList {
     }
     $constraints = array_values($constraints);
     $constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager();
+    $constraints[] = $constraint_manager->create('ValidDynamicReference', []);
     return $constraints;
   }
 
diff --git a/src/Plugin/Field/FieldType/DynamicEntityReferenceItem.php b/src/Plugin/Field/FieldType/DynamicEntityReferenceItem.php
index 32f11d0..a953264 100644
--- a/src/Plugin/Field/FieldType/DynamicEntityReferenceItem.php
+++ b/src/Plugin/Field/FieldType/DynamicEntityReferenceItem.php
@@ -34,8 +34,7 @@ use Drupal\dynamic_entity_reference\DataDynamicReferenceDefinition;
  *   no_ui = FALSE,
  *   list_class = "\Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceFieldItemList",
  *   default_widget = "dynamic_entity_reference_default",
- *   default_formatter = "dynamic_entity_reference_label",
- *   constraints = {"ValidDynamicReference" = {}}
+ *   default_formatter = "dynamic_entity_reference_label"
  * )
  */
 class DynamicEntityReferenceItem extends EntityReferenceItem {
diff --git a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraint.php b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraint.php
index 6661c17..f1960d2 100644
--- a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraint.php
+++ b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraint.php
@@ -21,7 +21,30 @@ class ValidDynamicReferenceConstraint extends Constraint {
    *
    * @var string
    */
-  public $message = 'The referenced entity (%type: %id) does not exist.';
+  public $message = 'This entity (%type: %id) cannot be referenced.';
+
+  /**
+   * Violation message when the entity does not exist.
+   *
+   * @var string
+   */
+  public $nonExistingMessage = 'The referenced entity (%type: %id) does not exist.';
+
+  /**
+   * Violation message when a new entity ("autocreate") is invalid.
+   *
+   * @var string
+   */
+  public $invalidAutocreateMessage = 'This entity (%type: %label) cannot be referenced.';
+
+  /**
+   * The default violation message.
+   *
+   * @var string
+   */
+  public $wrongIDMessage = 'The referenced entity (%type: %id) does not exist.';
+  public $wrongTypeMessage = 'The referenced entity type (%type) is not allowed for this field.';
+  public $wrongBundleMessage = 'The entity bundle must be one of %bundles, the selected entity is of bundle %bundle.';
 
   /**
    * Validation message when the target_id or target_type is empty.
diff --git a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php
index b369545..aa85080 100644
--- a/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php
+++ b/src/Plugin/Validation/Constraint/ValidDynamicReferenceConstraintValidator.php
@@ -2,50 +2,101 @@
 
 namespace Drupal\dynamic_entity_reference\Plugin\Validation\Constraint;
 
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\dynamic_entity_reference\Plugin\Field\FieldType\DynamicEntityReferenceItem;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
 /**
  * Checks if referenced entities are valid.
  */
-class ValidDynamicReferenceConstraintValidator extends ConstraintValidator {
+class ValidDynamicReferenceConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
+
+  /**
+   * The selection plugin manager.
+   *
+   * @var \Drupal\dynamic_entity_reference\SelectionPluginManager
+   */
+  protected $selectionManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a ValidReferenceConstraintValidator object.
+   *
+   * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_manager
+   *   The selection plugin manager.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(SelectionPluginManagerInterface $selection_manager, EntityTypeManagerInterface $entity_type_manager) {
+    $this->selectionManager = $selection_manager;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.dynamic_entity_reference_selection'),
+      $container->get('entity_type.manager')
+    );
+  }
 
   /**
    * {@inheritdoc}
    */
   public function validate($value, Constraint $constraint) {
-    /* @var \Drupal\Core\Field\FieldItemInterface $value */
+    /* @var \Drupal\dynamic_entity_reference\Plugin\Validation\Constraint\ValidDynamicReferenceConstraint $constraint */
+    /* @var \Drupal\Core\Field\FieldItemListInterface $value */
     if (!isset($value)) {
       return;
     }
-    // We don't use a regular NotNull constraint for the target_id property as
-    // a NULL value is valid if the entity property contains an unsaved entity.
-    // @see \Drupal\Core\TypedData\DataReferenceTargetDefinition::getConstraints
-    if (!$value->isEmpty() && $value->target_id === NULL && !$value->entity->isNew()) {
-      $this->context->addViolation($constraint->nullMessage, ['%property' => 'target_id']);
-      return;
-    }
-    // We don't use a regular NotNull constraint for the target_id property as
-    // a NULL value is valid if the entity property contains an unsaved entity.
-    // @see \Drupal\Core\TypedData\DataReferenceTargetDefinition::getConstraints
-    if (!$value->isEmpty() && $value->target_type === NULL && !$value->entity->isNew()) {
-      $this->context->addViolation($constraint->nullMessage, ['%property' => 'target_type']);
-      return;
-    }
-    $id = $value->get('target_id')->getValue();
-    $type = $value->get('target_type')->getValue();
-    $types = DynamicEntityReferenceItem::getTargetTypes($value->getFieldDefinition()->getSettings());
-    $valid_type = empty($type) || (!empty($type) && in_array($type, $types));
-    // '0' or NULL are considered valid empty references.
-    if (empty($id) && $valid_type) {
-      return;
-    }
-    $referenced_entity = $value->get('entity')->getValue();
-    /** @var \Drupal\dynamic_entity_reference\Plugin\Validation\Constraint\ValidDynamicReferenceConstraint $constraint */
-    if (!$valid_type || !$referenced_entity) {
-      $this->context->addViolation($constraint->message, ['%type' => $type, '%id' => $id]);
+    foreach ($value as $delta => $item) {
+      $valid_target_type = DynamicEntityReferenceItem::getTargetTypes($item->getFieldDefinition()
+        ->getSettings());
+      $target_id = $item->target_id;
+      $target_type = $item->target_type;
+      // We don't use a regular NotNull constraint for the target_id property as
+      // NULL is allowed if the entity property contains an unsaved entity.
+      // @see \Drupal\Core\TypedData\DataReferenceTargetDefinition::getConstraints()
+      if (!$item->isEmpty() && ($target_id === NULL || $target_type === NULL)) {
+        $property = $target_id ? $target_type : $target_id;
+        if (!$item->entity->isNew()) {
+          $this->context->buildViolation($constraint->nullMessage)
+            ->setParameter('%property', $property)
+            ->atPath((string) $delta . $property)
+            ->addViolation();
+          return;
+        }
+        // It is a new entity.
+        else {
+          // @todo validate new entity.
+        }
+      }
+      $valid_type = empty($target_type) || (!empty($target_type) && in_array($target_type, $valid_target_type));
+      if (!$valid_type) {
+        $this->context->buildViolation($constraint->wrongTypeMessage)
+          ->setParameter('%type', $target_type)
+          ->atPath((string) $delta . '.target_type')
+          ->setInvalidValue($target_type)
+          ->addViolation();
+      }
+      /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
+      $handler = $this->selectionManager->getSelectionHandler($value->getFieldDefinition(), NULL, $target_type);
+      // @todo validate target_id.
+      // @todo add bundle violations.
     }
+
   }
 
 }
