diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Exception/InvalidMapperDefinitionException.php b/core/lib/Drupal/Component/Plugin/Exception/InvalidPluginDefinitionException.php
similarity index 63%
rename from core/modules/config_translation/lib/Drupal/config_translation/Exception/InvalidMapperDefinitionException.php
rename to core/lib/Drupal/Component/Plugin/Exception/InvalidPluginDefinitionException.php
index eb56606..9951945 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Exception/InvalidMapperDefinitionException.php
+++ b/core/lib/Drupal/Component/Plugin/Exception/InvalidPluginDefinitionException.php
@@ -2,17 +2,15 @@
 
 /**
  * @file
- * Contains \Drupal\config_translation\Exception\InvalidMapperDefinitionException.
+ * Contains \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException.
  */
 
-namespace Drupal\config_translation\Exception;
-
-use Drupal\Component\Plugin\Exception\PluginException;
+namespace Drupal\Component\Plugin\Exception;
 
 /**
- * Defines a class for invalid configuration mapper definition exceptions.
+ * Defines a class for invalid plugin definition exceptions.
  */
-class InvalidMapperDefinitionException extends PluginException {
+class InvalidPluginDefinitionException extends PluginException {
 
   /**
    * The plugin ID of the mapper.
@@ -22,7 +20,7 @@ class InvalidMapperDefinitionException extends PluginException {
   protected $pluginId;
 
   /**
-   * Constructs a InvalidMapperDefinitionException.
+   * Constructs a InvalidPluginDefinitionException.
    *
    * @param string $plugin_id
    *   The plugin ID of the mapper.
diff --git a/core/lib/Drupal/Core/Config/Entity/DraggableListController.php b/core/lib/Drupal/Core/Config/Entity/DraggableListController.php
index 91a1dce..c606a47 100644
--- a/core/lib/Drupal/Core/Config/Entity/DraggableListController.php
+++ b/core/lib/Drupal/Core/Config/Entity/DraggableListController.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormInterface;
 
 /**
@@ -49,8 +48,8 @@
   /**
    * {@inheritdoc}
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage) {
+    parent::__construct($entity_info, $storage);
 
     // Check if the entity type supports weighting.
     if ($this->entityInfo->hasKey('weight')) {
diff --git a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php
index f6055ab..6bc8a23 100644
--- a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php
@@ -62,13 +62,12 @@ public function createAccess($entity_bundle = NULL, AccountInterface $account =
   public function resetCache();
 
   /**
-   * Sets the module handler for this form.
+   * Sets the module handler for this access controller.
    *
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    *
-   * @return self
-   *   The entity access controller.
+   * @return $this
    */
   public function setModuleHandler(ModuleHandlerInterface $module_handler);
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
index 525fd7c..e63679b 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
@@ -45,8 +45,7 @@ public function isDefaultFormLangcode(array $form_state);
    * @param string $operation
    *   The name of the current operation.
    *
-   * @return self
-   *   The entity form.
+   * @return $this
    */
   public function setOperation($operation);
 
@@ -106,6 +105,8 @@ public function getEntity();
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity the current form should operate upon.
+   *
+   * @return $this
    */
   public function setEntity(EntityInterface $entity);
 
@@ -158,8 +159,7 @@ public function submit(array $form, array &$form_state);
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
    *   The translation manager.
    *
-   * @return self
-   *   The entity form.
+   * @return $this
    */
   public function setTranslationManager(TranslationInterface $translation_manager);
 
@@ -169,8 +169,7 @@ public function setTranslationManager(TranslationInterface $translation_manager)
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    *
-   * @return self
-   *   The entity form.
+   * @return $this
    */
   public function setModuleHandler(ModuleHandlerInterface $module_handler);
 
diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php
index fdbc6a9..303e378 100644
--- a/core/lib/Drupal/Core/Entity/EntityListController.php
+++ b/core/lib/Drupal/Core/Entity/EntityListController.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Core\Entity;
 
-use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -59,8 +58,7 @@ class EntityListController implements EntityListControllerInterface, EntityContr
   public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
     return new static(
       $entity_info,
-      $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler')
+      $container->get('entity.manager')->getStorageController($entity_info->id())
     );
   }
 
@@ -71,14 +69,11 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) {
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage) {
     $this->entityType = $entity_info->id();
     $this->storage = $storage;
     $this->entityInfo = $entity_info;
-    $this->moduleHandler = $module_handler;
   }
 
   /**
@@ -216,30 +211,16 @@ public function render() {
    * See the t() documentation for details.
    */
   protected function t($string, array $args = array(), array $options = array()) {
-    return $this->translationManager()->translate($string, $args, $options);
+    return $this->translationManager->translate($string, $args, $options);
   }
 
   /**
-   * Gets the translation manager.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslationInterface
-   *   The translation manager.
-   */
-  protected function translationManager() {
-    if (!$this->translationManager) {
-      $this->translationManager = \Drupal::translation();
-    }
-    return $this->translationManager;
-  }
-
-  /**
-   * Sets the translation manager for this form.
+   * Sets the translation manager for this list.
    *
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
    *   The translation manager.
    *
-   * @return self
-   *   The entity form.
+   * @return $this
    */
   public function setTranslationManager(TranslationInterface $translation_manager) {
     $this->translationManager = $translation_manager;
@@ -247,6 +228,19 @@ public function setTranslationManager(TranslationInterface $translation_manager)
   }
 
   /**
+   * Sets the module handler for this list.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return $this
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+    return $this;
+  }
+
+  /**
    * Returns the title of the page.
    *
    * @return string
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 9185c32..afcd454 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -7,9 +7,11 @@
 
 namespace Drupal\Core\Entity;
 
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
+use Drupal\Component\Plugin\Exception\UnknownPluginException;
 use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -143,7 +145,6 @@ public function __construct(\Traversable $namespaces, ContainerInterface $contai
     $this->discovery = new InfoHookDecorator($this->discovery, 'entity_info');
     $this->discovery = new AlterDecorator($this->discovery, 'entity_info');
     $this->discovery = new CacheDecorator($this->discovery, 'entity_info:' . $this->languageManager->getCurrentLanguage()->id, 'cache', CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
-    $this->factory = new DefaultFactory($this->discovery);
     $this->container = $container;
   }
 
@@ -159,6 +160,20 @@ public function clearCachedDefinitions() {
   /**
    * {@inheritdoc}
    */
+  public function getDefinition($entity_type_id, $exception_on_invalid = FALSE) {
+    if (($entity_type = parent::getDefinition($entity_type_id)) && class_exists($entity_type->getClass())) {
+      return $entity_type;
+    }
+    elseif (!$exception_on_invalid) {
+      return NULL;
+    }
+
+    throw new UnknownPluginException($entity_type_id, sprintf('The "%s" entity type does not exist.', $entity_type_id));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function hasController($entity_type, $controller_type) {
     if ($definition = $this->getDefinition($entity_type)) {
       return $definition->hasController($controller_type);
@@ -169,55 +184,15 @@ public function hasController($entity_type, $controller_type) {
   /**
    * {@inheritdoc}
    */
-  public function getControllerClass($entity_type, $controller_type, $nested = NULL) {
-    $info = $this->getDefinition($entity_type);
-    if (!$info) {
-      throw new \InvalidArgumentException(sprintf('The %s entity type does not exist.', $entity_type));
-    }
-
-    if (!$info->hasController($controller_type)) {
-      throw new \InvalidArgumentException(sprintf('The entity type (%s) did not specify a %s controller.', $entity_type, $controller_type));
-    }
-
-    $class = $info->getController($controller_type);
-
-    // Some class definitions can be nested.
-    if (isset($nested)) {
-      if (empty($class[$nested])) {
-        throw new \InvalidArgumentException(sprintf("The entity type (%s) did not specify a %s controller: %s.", $entity_type, $controller_type, $nested));
-      }
-
-      $class = $class[$nested];
-    }
-
-    if (!class_exists($class)) {
-      throw new \InvalidArgumentException(sprintf('The entity type (%s) %s controller "%s" does not exist.', $entity_type, $controller_type, $class));
-    }
-
-    return $class;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getStorageController($entity_type) {
-    return $this->getController($entity_type, 'storage');
+    return $this->getController($entity_type, 'storage', 'getStorage');
   }
 
   /**
    * {@inheritdoc}
    */
   public function getListController($entity_type) {
-    if (!isset($this->controllers['listing'][$entity_type])) {
-      $class = $this->getControllerClass($entity_type, 'list');
-      if (in_array('Drupal\Core\Entity\EntityControllerInterface', class_implements($class))) {
-        $this->controllers['listing'][$entity_type] = $class::createInstance($this->container, $this->getDefinition($entity_type));
-      }
-      else {
-        $this->controllers['listing'][$entity_type] = new $class($entity_type, $this->getStorageController($entity_type));
-      }
-    }
-    return $this->controllers['listing'][$entity_type];
+    return $this->getController($entity_type, 'list', 'getList');
   }
 
   /**
@@ -225,7 +200,9 @@ public function getListController($entity_type) {
    */
   public function getFormController($entity_type, $operation) {
     if (!isset($this->controllers['form'][$operation][$entity_type])) {
-      $class = $this->getControllerClass($entity_type, 'form', $operation);
+      if (!$class = $this->getDefinition($entity_type, TRUE)->getForm($operation)) {
+        throw new InvalidPluginDefinitionException($entity_type, sprintf('The "%s" entity type did not specify a "%s" form class.', $entity_type, $operation));
+      }
       if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($class))) {
         $controller = $class::create($this->container);
       }
@@ -246,40 +223,44 @@ public function getFormController($entity_type, $operation) {
    * {@inheritdoc}
    */
   public function getViewBuilder($entity_type) {
-    return $this->getController($entity_type, 'view_builder');
+    return $this->getController($entity_type, 'view_builder', 'getViewBuilder');
   }
 
   /**
    * {@inheritdoc}
    */
   public function getAccessController($entity_type) {
-    if (!isset($this->controllers['access'][$entity_type])) {
-      $controller = $this->getController($entity_type, 'access');
-      $controller->setModuleHandler($this->moduleHandler);
-    }
-    return $this->controllers['access'][$entity_type];
+    return $this->getController($entity_type, 'access', 'getAccess');
   }
 
   /**
-   * Creates a new controller instance.
-   *
-   * @param string $entity_type
-   *   The entity type for this access controller.
-   * @param string $controller_type
-   *   The controller type to create an instance for.
-   *
-   * @return mixed.
-   *   A controller instance.
+   * {@inheritdoc}
    */
-  protected function getController($entity_type, $controller_type) {
+  public function getController($entity_type, $controller_type, $controller_getter = NULL) {
     if (!isset($this->controllers[$controller_type][$entity_type])) {
-      $class = $this->getControllerClass($entity_type, $controller_type);
-      if (in_array('Drupal\Core\Entity\EntityControllerInterface', class_implements($class))) {
-        $this->controllers[$controller_type][$entity_type] = $class::createInstance($this->container, $this->getDefinition($entity_type));
+      $definition = $this->getDefinition($entity_type, TRUE);
+      if ($controller_getter) {
+        $class = $definition->{$controller_getter}();
       }
       else {
-        $this->controllers[$controller_type][$entity_type] = new $class($this->getDefinition($entity_type));
+        $class = $definition->getController($controller_type);
       }
+      if (!$class) {
+        throw new InvalidPluginDefinitionException($entity_type, sprintf('The "%s" entity type did not specify a %s class.', $entity_type, $controller_type));
+      }
+      if (is_subclass_of($class, 'Drupal\Core\Entity\EntityControllerInterface')) {
+        $controller = $class::createInstance($this->container, $definition);
+      }
+      else {
+        $controller = new $class($definition);
+      }
+      if (method_exists($controller, 'setModuleHandler')) {
+        $controller->setModuleHandler($this->moduleHandler);
+      }
+      if (method_exists($controller, 'setTranslationManager')) {
+        $controller->setTranslationManager($this->translationManager);
+      }
+      $this->controllers[$controller_type][$entity_type] = $controller;
     }
     return $this->controllers[$controller_type][$entity_type];
   }
@@ -304,8 +285,7 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $
    * {@inheritdoc}
    */
   public function getAdminRouteInfo($entity_type, $bundle) {
-    $entity_info = $this->getDefinition($entity_type);
-    if ($admin_form = $entity_info->getLinkTemplate('admin-form')) {
+    if (($entity_info = $this->getDefinition($entity_type)) && $admin_form = $entity_info->getLinkTemplate('admin-form')) {
       return array(
         'route_name' => $admin_form,
         'route_parameters' => array(
@@ -329,8 +309,7 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) {
         // @todo: Refactor to allow for per-bundle overrides.
         // See https://drupal.org/node/2114707.
         $entity_info = $this->getDefinition($entity_type);
-        $definition = array('class' => $entity_info->getClass());
-        $class = $this->factory->getPluginClass($entity_type, $definition);
+        $class = $entity_info->getClass();
 
         $this->entityFieldInfo[$entity_type] = array(
           'definitions' => $class::baseFieldDefinitions($entity_type),
@@ -350,6 +329,7 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) {
         // Automatically set the field name for non-configurable fields.
         foreach (array('definitions', 'optional') as $key) {
           foreach ($this->entityFieldInfo[$entity_type][$key] as $field_name => &$definition) {
+            // @todo This should check FieldDefinitionInterface.
             if ($definition instanceof FieldDefinition) {
               $definition->setName($field_name);
             }
@@ -366,7 +346,7 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) {
         foreach (array('definitions', 'optional') as $key) {
           foreach ($this->entityFieldInfo[$entity_type][$key] as $field_name => &$definition) {
             if (isset($untranslatable_fields[$field_name]) && $definition->isTranslatable()) {
-              throw new \LogicException(format_string('The @field field cannot be translatable.', array('@field' => $definition->getLabel())));
+              throw new \LogicException(String::format('The @field field cannot be translatable.', array('@field' => $definition->getLabel())));
             }
           }
         }
diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
index 302cce5..902d880 100644
--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -105,22 +105,6 @@ public function getFieldDefinitionsByConstraints($entity_type, array $constraint
   public function getStorageController($entity_type);
 
   /**
-   * Returns an entity controller class.
-   *
-   * @param string $entity_type
-   *   The name of the entity type
-   * @param string $controller_type
-   *   The name of the controller.
-   * @param string|null $nested
-   *   (optional) If this controller definition is nested, the name of the key.
-   *   Defaults to NULL.
-   *
-   * @return string
-   *   The class name for this controller instance.
-   */
-  public function getControllerClass($entity_type, $controller_type, $nested = NULL);
-
-  /**
    * Get the bundle info of all entity types.
    *
    * @return array
@@ -187,6 +171,23 @@ public function clearCachedFieldDefinitions();
   public function hasController($entity_type, $controller_type);
 
   /**
+   * Creates a new controller instance.
+   *
+   * @param string $entity_type
+   *   The entity type for this controller.
+   * @param string $controller_type
+   *   The controller type to create an instance for.
+   * @param string $controller_getter
+   *   (optional) The method to call on the entity type object to get the controller class.
+   *
+   * @return mixed
+   *   A controller instance.
+   *
+   * @throws \InvalidArgumentException
+   */
+  public function getController($entity_type, $controller_type, $controller_getter = NULL);
+
+  /**
    * Returns the built and processed entity form for the given entity.
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
@@ -247,13 +248,20 @@ public function getTranslationFromContext(EntityInterface $entity, $langcode = N
   /**
    * Returns the entity type info for a specific entity type.
    *
-   * @param string $entity_type_name
-   *   The name of the entity type.
+   * @param string $entity_type_id
+   *   The ID of the entity type.
+   * @param bool $exception_on_invalid
+   *   (optional) If TRUE, an invalid entity type ID will throw an exception.
+   *   Defaults to FALSE.
    *
    * @return \Drupal\Core\Entity\EntityTypeInterface|null
-   *   Either the entity type object, or NULL if the name does not exist.
+   *   Returns the entity type object, or NULL if the entity type ID is invalid
+   *   and $exception_on_invalid is TRUE.
+   *
+   * @throws \InvalidArgumentException
+   *   Thrown if $entity_type_id is invalid and $exception_on_invalid is TRUE.
    */
-  public function getDefinition($entity_type_name);
+  public function getDefinition($entity_type_id, $exception_on_invalid = FALSE);
 
   /**
    * Returns an array of entity type info, keyed by entity type name.
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
index 8774ac2..b74cfba 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity;
 use Drupal\Core\Entity\Query\QueryInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 
 /**
  * A base entity storage controller class.
@@ -44,6 +45,13 @@
   protected $entityInfo;
 
   /**
+   * The module handler to invoke hooks on.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
    * Name of the entity's ID field in the entity database table.
    *
    * @var string
@@ -149,9 +157,9 @@ protected function cacheSet($entities) {
    */
   protected function invokeHook($hook, EntityInterface $entity) {
     // Invoke the hook.
-    module_invoke_all($this->entityType . '_' . $hook, $entity);
+    $this->moduleHandler->invokeAll($this->entityType . '_' . $hook, array($entity));
     // Invoke the respective entity-level hook.
-    module_invoke_all('entity_' . $hook, $entity, $this->entityType);
+    $this->moduleHandler->invokeAll('entity_' . $hook, array($entity, $this->entityType));
   }
 
   /**
@@ -164,12 +172,12 @@ protected function postLoad(array &$queried_entities) {
     $entity_class = $this->entityInfo->getClass();
     $entity_class::postLoad($this, $queried_entities);
     // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
+    foreach ($this->moduleHandler->getImplementations('entity_load') as $module) {
       $function = $module . '_entity_load';
       $function($queried_entities, $this->entityType);
     }
     // Call hook_TYPE_load().
-    foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
+    foreach ($this->moduleHandler->getImplementations($this->entityType . '_load') as $module) {
       $function = $module . '_' . $this->entityType . '_load';
       $function($queried_entities);
     }
@@ -201,4 +209,17 @@ public function loadByProperties(array $values = array()) {
     return $result ? $this->loadMultiple($result) : array();
   }
 
+  /**
+   * Sets the module handler for this storage.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return $this
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+    return $this;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index 1d86e02..e7ef60b 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -317,9 +317,13 @@ public function getControllers() {
   /**
    * {@inheritdoc}
    */
-  public function getController($controller_type) {
-    $controllers = $this->getControllers();
-    return $controllers[$controller_type];
+  public function getController($controller_type, $nested = FALSE) {
+    if ($this->hasController($controller_type, $nested)) {
+      $controllers = $this->getControllers();
+      return $nested ? $controllers[$controller_type][$nested] : $controllers[$controller_type];
+    }
+
+    return '';
   }
 
   /**
@@ -333,9 +337,37 @@ public function setController($controller_type, $value) {
   /**
    * {@inheritdoc}
    */
-  public function hasController($controller_type) {
+  public function hasController($controller_type, $nested = FALSE) {
     $controllers = $this->getControllers();
-    return isset($controllers[$controller_type]);
+    if (!isset($controllers[$controller_type]) || ($nested && !isset($controllers[$controller_type][$nested]))) {
+      return FALSE;
+    }
+    $controller = $controllers[$controller_type];
+    if ($nested) {
+      $controller = $controller[$nested];
+    }
+    return class_exists($controller);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getStorage() {
+    return $this->getController('storage');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setStorage($class) {
+    $this->controllers['storage'] = $class;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getForm($operation) {
+    return $this->getController('form', $operation);
   }
 
   /**
@@ -349,6 +381,20 @@ public function setForm($operation, $class) {
   /**
    * {@inheritdoc}
    */
+  public function hasForms() {
+    return !empty($this->controllers['form']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getList() {
+    return $this->getController('list');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function setList($class) {
     $this->controllers['list'] = $class;
     return $this;
@@ -357,6 +403,36 @@ public function setList($class) {
   /**
    * {@inheritdoc}
    */
+  public function getViewBuilder() {
+    return $this->getController('view_builder');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setViewBuilder($class) {
+    $this->controllers['view_builder'] = $class;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAccess() {
+    return $this->getController('access');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAccess($class) {
+    $this->controllers['access'] = $class;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getAdminPermission() {
     return $this->admin_permission ?: FALSE;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index 4cb05aa..dfcc4da 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -160,11 +160,13 @@ public function setClass($class);
    *
    * @param string $controller_type
    *   The type of controller to check.
+   * @param bool $nested
+   *   (optional) If this controller has a nested definition. Defaults to FALSE.
    *
    * @return bool
    *   TRUE if a controller of this type exists, FALSE otherwise.
    */
-  public function hasController($controller_type);
+  public function hasController($controller_type, $nested = FALSE);
 
   /**
    * @param string $controller_type
@@ -202,6 +204,35 @@ public function getController($controller_type);
   public function getControllers();
 
   /**
+   * Returns the storage class.
+   *
+   * @return string
+   *   The class for this entity type's storage.
+   */
+  public function getStorage();
+
+  /**
+   * Sets the storage class.
+   *
+   * @param string $class
+   *   The class for this entity type's storage.
+   *
+   * @return $this
+   */
+  public function setStorage($class);
+
+  /**
+   * Returns the form class for a specific operation.
+   *
+   * @param string $operation
+   *   The name of the operation to use, e.g., 'default'.
+   *
+   * @return string
+   *   The class for this operation's form for this entity type.
+   */
+  public function getForm($operation);
+
+  /**
    * Sets a form class for a specific operation.
    *
    * @param string $operation
@@ -214,6 +245,22 @@ public function getControllers();
   public function setForm($operation, $class);
 
   /**
+   * Indicates if this entity type has any forms.
+   *
+   * @return bool
+   *   TRUE if there are any forms for this entity type, FALSE otherwise.
+   */
+  public function hasForms();
+
+  /**
+   * Returns the list class.
+   *
+   * @return string
+   *   The class for this entity type's list.
+   */
+  public function getList();
+
+  /**
    * Sets the listing class.
    *
    * @param string $class
@@ -224,6 +271,42 @@ public function setForm($operation, $class);
   public function setList($class);
 
   /**
+   * Returns the view builder class.
+   *
+   * @return string
+   *   The class for this entity type's view builder.
+   */
+  public function getViewBuilder();
+
+  /**
+   * Returns the view builder class.
+   *
+   * @param string $class
+   *   The class for this entity type's view builder.
+   *
+   * @return $this
+   */
+  public function setViewBuilder($class);
+
+  /**
+   * Returns the access class.
+   *
+   * @return string
+   *   The class for this entity type's access.
+   */
+  public function getAccess();
+
+  /**
+   * Returns the access class.
+   *
+   * @param string $class
+   *   The class for this entity type's access.
+   *
+   * @return $this
+   */
+  public function setAccess($class);
+
+  /**
    * Indicates if the entity type is a subclass of the given class or interface.
    *
    * @param string $class
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
index 6442577..b661fb4 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Entity;
 
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -39,6 +40,13 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
   protected $entityManager;
 
   /**
+   * The module handler to invoke hooks on.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
    * The cache bin used to store the render cache.
    *
    * @todo Defaults to 'cache' for now, until http://drupal.org/node/1194136 is
@@ -285,4 +293,17 @@ protected function isViewModeCacheable($view_mode) {
     return !empty($view_modes_info[$view_mode]['cache']);
   }
 
+  /**
+   * Sets the module handler for this view builder.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return $this
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+    return $this;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
index b3f9b5e..15235f9 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/CacheDecorator.php
@@ -132,7 +132,7 @@ public function getDefinitions() {
    *   and would actually be returned by the getDefinitions() method.
    */
   protected function getCachedDefinitions() {
-    if (!isset($this->definitions) && isset($this->cacheKey) && $cache = cache($this->cacheBin)->get($this->cacheKey)) {
+    if (!isset($this->definitions) && isset($this->cacheKey) && $cache = $this->cache($this->cacheBin)->get($this->cacheKey)) {
       $this->definitions = $cache->data;
     }
     return $this->definitions;
@@ -146,7 +146,7 @@ protected function getCachedDefinitions() {
    */
   protected function setCachedDefinitions($definitions) {
     if (isset($this->cacheKey)) {
-      cache($this->cacheBin)->set($this->cacheKey, $definitions, $this->cacheExpire, $this->cacheTags);
+      $this->cache($this->cacheBin)->set($this->cacheKey, $definitions, $this->cacheExpire, $this->cacheTags);
     }
     $this->definitions = $definitions;
   }
@@ -157,11 +157,11 @@ protected function setCachedDefinitions($definitions) {
   public function clearCachedDefinitions() {
     // If there are any cache tags, clear cache based on those.
     if (!empty($this->cacheTags)) {
-      cache($this->cacheBin)->deleteTags($this->cacheTags);
+      $this->cache($this->cacheBin)->deleteTags($this->cacheTags);
     }
     // Otherwise, just delete the specified cache key.
     else if (isset($this->cacheKey)) {
-      cache($this->cacheBin)->delete($this->cacheKey);
+      $this->cache($this->cacheBin)->delete($this->cacheKey);
     }
     $this->definitions = NULL;
   }
@@ -173,4 +173,11 @@ public function __call($method, $args) {
     return call_user_func_array(array($this->decorated, $method), $args);
   }
 
+  /**
+   * Wraps the \Drupal::cache() method.
+   */
+  protected function cache($bin) {
+    return \Drupal::cache($bin);
+  }
+
 }
diff --git a/core/modules/action/lib/Drupal/action/ActionListController.php b/core/modules/action/lib/Drupal/action/ActionListController.php
index 03f7b75..ee612c9 100644
--- a/core/modules/action/lib/Drupal/action/ActionListController.php
+++ b/core/modules/action/lib/Drupal/action/ActionListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Config\Entity\ConfigEntityListController;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -42,11 +41,9 @@ class ActionListController extends ConfigEntityListController implements EntityC
    *   The action storage controller.
    * @param \Drupal\Core\Action\ActionManager $action_manager
    *   The action plugin manager.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ActionManager $action_manager, ModuleHandlerInterface $module_handler) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ActionManager $action_manager) {
+    parent::__construct($entity_info, $storage);
 
     $this->actionManager = $action_manager;
   }
@@ -58,8 +55,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('plugin.manager.action'),
-      $container->get('module_handler')
+      $container->get('plugin.manager.action')
     );
   }
 
diff --git a/core/modules/block/lib/Drupal/block/BlockListController.php b/core/modules/block/lib/Drupal/block/BlockListController.php
index 926558b..da7cbaa 100644
--- a/core/modules/block/lib/Drupal/block/BlockListController.php
+++ b/core/modules/block/lib/Drupal/block/BlockListController.php
@@ -60,13 +60,11 @@ class BlockListController extends ConfigEntityListController implements FormInte
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Component\Plugin\PluginManagerInterface $block_manager
    *   The block manager.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, PluginManagerInterface $block_manager) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, PluginManagerInterface $block_manager) {
+    parent::__construct($entity_info, $storage);
 
     $this->blockManager = $block_manager;
   }
@@ -78,7 +76,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('plugin.manager.block')
     );
   }
diff --git a/core/modules/block/lib/Drupal/block/BlockViewBuilder.php b/core/modules/block/lib/Drupal/block/BlockViewBuilder.php
index 5aed185..105fcb1 100644
--- a/core/modules/block/lib/Drupal/block/BlockViewBuilder.php
+++ b/core/modules/block/lib/Drupal/block/BlockViewBuilder.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\block;
 
+use Drupal\Core\Entity\EntityViewBuilder;
 use Drupal\Core\Entity\EntityViewBuilderInterface;
 use Drupal\Core\Entity\EntityInterface;
 
 /**
  * Provides a Block view builder.
  */
-class BlockViewBuilder implements EntityViewBuilderInterface {
+class BlockViewBuilder extends EntityViewBuilder {
 
   /**
    * {@inheritdoc}
@@ -57,7 +58,7 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
         $build[$entity_id] = array();
       }
 
-      drupal_alter(array('block_view', "block_view_$base_id"), $build[$entity_id], $plugin);
+      $this->moduleHandler->alter(array('block_view', "block_view_$base_id"), $build[$entity_id], $plugin);
 
       // @todo Remove after fixing http://drupal.org/node/1989568.
       $build[$entity_id]['#block'] = $entity;
diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
index d23ee11..fe63286 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
@@ -8,13 +8,10 @@
 namespace Drupal\comment;
 
 use Drupal\Core\Access\CsrfTokenGenerator;
-use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityViewBuilderInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Entity\EntityViewBuilder;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\field\FieldInfo;
@@ -23,7 +20,7 @@
 /**
  * Render controller for comments.
  */
-class CommentViewBuilder extends EntityViewBuilder implements EntityViewBuilderInterface, EntityControllerInterface {
+class CommentViewBuilder extends EntityViewBuilder {
 
   /**
    * The field info service.
@@ -55,7 +52,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('entity.manager'),
       $container->get('language_manager'),
       $container->get('field.info'),
-      $container->get('module_handler'),
       $container->get('csrf_token')
     );
   }
@@ -71,15 +67,12 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
    *   The language manager.
    * @param \Drupal\field\FieldInfo $field_info
    *   The field info service.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler service.
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token manager service.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, FieldInfo $field_info, ModuleHandlerInterface $module_handler, CsrfTokenGenerator $csrf_token) {
+  public function __construct(EntityTypeInterface $entity_info, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, FieldInfo $field_info, CsrfTokenGenerator $csrf_token) {
     parent::__construct($entity_info, $entity_manager, $language_manager);
     $this->fieldInfo = $field_info;
-    $this->moduleHandler = $module_handler;
     $this->csrfToken = $csrf_token;
   }
 
diff --git a/core/modules/config_translation/config_translation.api.php b/core/modules/config_translation/config_translation.api.php
index aa1f7f0..c9e6656 100644
--- a/core/modules/config_translation/config_translation.api.php
+++ b/core/modules/config_translation/config_translation.api.php
@@ -56,7 +56,6 @@ function hook_config_translation_info(&$info) {
           'title' => t('!label field'),
           'class' => '\Drupal\config_translation\ConfigFieldInstanceMapper',
           'base_entity_type' => $entity_type,
-          'list_controller' => '\Drupal\config_translation\Controller\ConfigTranslationFieldInstanceListController',
           'weight' => 10,
         );
       }
diff --git a/core/modules/config_translation/config_translation.module b/core/modules/config_translation/config_translation.module
index 33a2ee7..fdb66f6 100644
--- a/core/modules/config_translation/config_translation.module
+++ b/core/modules/config_translation/config_translation.module
@@ -70,6 +70,25 @@ function config_translation_theme() {
 }
 
 /**
+ * Implements hook_entity_info().
+ */
+function config_translation_entity_info($entity_info) {
+  /** @var $entity_info \Drupal\Core\Entity\EntityTypeInterface[] */
+  foreach ($entity_info as $entity_type_id => $entity_type) {
+    if ($entity_type_id == 'block') {
+      $class = 'Drupal\config_translation\Controller\ConfigTranslationBlockListController';
+    }
+    elseif ($entity_type_id == 'field_instance') {
+      $class = 'Drupal\config_translation\Controller\ConfigTranslationFieldInstanceListController';
+    }
+    else {
+      $class = 'Drupal\config_translation\Controller\ConfigTranslationEntityListController';
+    }
+    $entity_type->setController('config_translation_list', $class);
+  }
+}
+
+/**
  * Implements hook_config_translation_info().
  */
 function config_translation_config_translation_info(&$info) {
@@ -97,7 +116,6 @@ function config_translation_config_translation_info(&$info) {
           'title' => '!label field',
           'class' => '\Drupal\config_translation\ConfigFieldInstanceMapper',
           'base_entity_type' => $entity_type,
-          'list_controller' => '\Drupal\config_translation\Controller\ConfigTranslationFieldInstanceListController',
           'weight' => 10,
         );
       }
@@ -128,11 +146,6 @@ function config_translation_config_translation_info(&$info) {
       'entity_type' => $entity_type,
       'weight' => 10,
     );
-
-    if ($entity_type == 'block') {
-      // Blocks placements need a specific list controller.
-      $info['block']['list_controller'] = '\Drupal\config_translation\Controller\ConfigTranslationBlockListController';
-    }
   }
 }
 
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php b/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
index 4331d6f..3622b73 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/ConfigMapperManager.php
@@ -8,7 +8,7 @@
 namespace Drupal\config_translation;
 
 use Drupal\Component\Utility\String;
-use Drupal\config_translation\Exception\InvalidMapperDefinitionException;
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\Schema\ArrayElement;
 use Drupal\Core\Config\TypedConfigManager;
@@ -41,7 +41,6 @@ class ConfigMapperManager extends DefaultPluginManager implements ConfigMapperMa
     'names' => array(),
     'weight' => 20,
     'class' => '\Drupal\config_translation\ConfigNamesMapper',
-    'list_controller' => 'Drupal\config_translation\Controller\ConfigTranslationEntityListController',
   );
 
   /**
@@ -117,11 +116,7 @@ public function processDefinition(&$definition, $plugin_id) {
     parent::processDefinition($definition, $plugin_id);
 
     if (!isset($definition['base_route_name'])) {
-      throw new InvalidMapperDefinitionException($plugin_id, String::format("The plugin definition of the mapper '%plugin_id' does not contain a base_route_name.", array('%plugin_id' => $plugin_id)));
-    }
-
-    if (!is_subclass_of($definition['list_controller'], 'Drupal\config_translation\Controller\ConfigTranslationEntityListControllerInterface')) {
-      throw new InvalidMapperDefinitionException($plugin_id, String::format("The list_controller '%list_controller' for plugin '%plugin_id' does not implement the expected interface Drupal\config_translation\Controller\ConfigTranslationEntityListControllerInterface.", array('%list_controller' => $definition['list_controller'], '%plugin_id' => $plugin_id)));
+      throw new InvalidPluginDefinitionException($plugin_id, String::format("The plugin definition of the mapper '%plugin_id' does not contain a base_route_name.", array('%plugin_id' => $plugin_id)));
     }
   }
 
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php
index 35c10cc..7151954 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php
@@ -11,7 +11,8 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines the config translation controller for blocks.
@@ -28,9 +29,20 @@ class ConfigTranslationBlockListController extends ConfigTranslationEntityListCo
   /**
    * {@inheritdoc}
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) {
-    parent::__construct($entity_info, $storage, $module_handler);
-    $this->themes = list_themes();
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ThemeHandlerInterface $theme_handler) {
+    parent::__construct($entity_info, $storage);
+    $this->themes = $theme_handler->listInfo();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
+    return new static(
+      $entity_info,
+      $container->get('entity.manager')->getStorageController($entity_info->id()),
+      $container->get('theme_handler')
+    );
   }
 
   /**
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php
index 09a9de6..8c09840 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php
@@ -127,4 +127,12 @@ protected function sortRowsMultiple($a, $b, $keys) {
     return strnatcasecmp($a_value, $b_value);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setMapperDefinition($mapper_definition) {
+    // @todo Why is this method called on all config list controllers?
+    return $this;
+  }
+
 }
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListControllerInterface.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListControllerInterface.php
index d342808..f2340b3 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListControllerInterface.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListControllerInterface.php
@@ -27,4 +27,14 @@
    */
   public function sortRows($a, $b);
 
+  /**
+   * Sets the config translation mapper definition.
+   *
+   * @param mixed $mapper_definition
+   *   The plugin definition of the config translation mapper.
+   *
+   * @return $this
+   */
+  public function setMapperDefinition($mapper_definition);
+
 }
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php
index 2f8630a..736aee9 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\field\Field;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -51,25 +50,14 @@ class ConfigTranslationFieldInstanceListController extends ConfigTranslationEnti
   protected $entityManager;
 
   /**
-   * Instantiates a new instance of this entity controller.
-   *
-   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
-   *   The service container this object should use.
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
-   *   The entity info for the entity type.
-   * @param array $definition
-   *   (optional) The plugin definition of the config translation mapper.
-   *
-   * @return static
-   *   A new instance of the entity controller.
+   * {@inheritdoc}
    */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info, array $definition = array()) {
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
+    $entity_manager = $container->get('entity.manager');
     return new static(
       $entity_info,
-      $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
-      $container->get('entity.manager'),
-      $definition
+      $entity_manager->getStorageController($entity_info->id()),
+      $entity_manager
     );
   }
 
@@ -80,19 +68,22 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
-   * @param array $definition
-   *   The plugin definition of the config translation mapper.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager, array $definition) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, EntityManagerInterface $entity_manager) {
+    parent::__construct($entity_info, $storage);
     $this->entityManager = $entity_manager;
-    $this->baseEntityType = $definition['base_entity_type'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setMapperDefinition($mapper_definition) {
+    $this->baseEntityType = $mapper_definition['base_entity_type'];
     $this->baseEntityInfo = $this->entityManager->getDefinition($this->baseEntityType);
     $this->baseEntityBundles = $this->entityManager->getBundleInfo($this->baseEntityType);
+    return $this;
   }
 
   /**
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php
index 14bd763..e8bdad3 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php
@@ -74,10 +74,10 @@ public function listing() {
     // list controller defined, use it. Other mappers, for examples the ones for
     // node_type and block, fallback to the generic configuration translation
     // list controller.
-    $class = $this->mapperDefinition['list_controller'];
-    /** @var \Drupal\config_translation\Controller\ConfigTranslationEntityListControllerInterface $controller */
-    $controller = new $class($this->entityManager()->getDefinition($entity_type), $this->entityManager()->getStorageController($entity_type), $this->moduleHandler(), $this->entityManager(), $this->mapperDefinition);
-    $build = $controller->render();
+    $build = $this->entityManager()
+      ->getController($entity_type, 'config_translation_list')
+      ->setMapperDefinition($this->mapperDefinition)
+      ->render();
     $build['#title'] = $this->mapper->getTypeLabel();
     return $build;
   }
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php b/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php
index 7bf8ea0..89d03b8 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php
@@ -44,8 +44,7 @@ public function access(Route $route, Request $request, AccountInterface $account
     if ($entity = $request->attributes->get($entity_type)) {
       $route_requirements = $route->getRequirements();
       $operation = $route_requirements['_access_content_translation_manage'];
-      $controller_class = $this->entityManager->getControllerClass($entity_type, 'translation');
-      $controller = new $controller_class($entity->entityInfo());
+      $controller = content_translation_controller($entity_type);
 
       // Load translation.
       $translations = $entity->getTranslationLanguages();
diff --git a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php
index e0f1d0f..4160f99 100644
--- a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php
+++ b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php
@@ -74,7 +74,7 @@ public function viewModeTypeSelection() {
   public function formModeTypeSelection() {
     $entity_types = array();
     foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) {
-      if ($entity_info->isFieldable() && $entity_info->hasController('form')) {
+      if ($entity_info->isFieldable() && $entity_info->hasForms()) {
         $entity_types[$entity_type] = array(
           'title' => $entity_info->getLabel(),
           'href' => 'admin/structure/display-modes/form/add/' . $entity_type,
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php
index 8946534..7f18505 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -33,13 +32,11 @@ class EntityDisplayModeListController extends ConfigEntityListController {
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_info_complete
    *   The entity info for all entity types.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, array $entity_info_complete) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, array $entity_info_complete) {
+    parent::__construct($entity_info, $storage);
 
     $this->entityInfoComplete = $entity_info_complete;
   }
@@ -52,7 +49,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $entity_manager->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $entity_manager->getDefinitions()
     );
   }
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormModeListController.php b/core/modules/entity/lib/Drupal/entity/EntityFormModeListController.php
index 0ae68f1..9f42ff2 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityFormModeListController.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormModeListController.php
@@ -19,11 +19,10 @@ class EntityFormModeListController extends EntityDisplayModeListController {
    *   The entity type of the entity that needs to be validated.
    *
    * @return bool
-   *   TRUE if the entity has the correct controller, FALSE if the entity
-   *   doesn't has the correct controller.
+   *   TRUE if the entity has any form controllers, FALSE otherwise.
    */
   protected function isValidEntity($entity_type) {
-    return $this->entityInfoComplete[$entity_type]->hasController('form');
+    return $this->entityInfoComplete[$entity_type]->hasForms();
   }
 
 }
diff --git a/core/modules/entity/lib/Drupal/entity/Form/EntityFormModeAddForm.php b/core/modules/entity/lib/Drupal/entity/Form/EntityFormModeAddForm.php
index ce27c0f..ffacd4f 100644
--- a/core/modules/entity/lib/Drupal/entity/Form/EntityFormModeAddForm.php
+++ b/core/modules/entity/lib/Drupal/entity/Form/EntityFormModeAddForm.php
@@ -19,7 +19,7 @@ class EntityFormModeAddForm extends EntityDisplayModeAddForm {
    */
   protected function prepareEntity() {
     $definition = $this->entityManager->getDefinition($this->entityType);
-    if (!$definition->isFieldable() || !$definition->hasController('form')) {
+    if (!$definition->isFieldable() || !$definition->hasForms()) {
       throw new NotFoundHttpException();
     }
 
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
index e9e65c4..172aee4 100644
--- a/core/modules/field/field.views.inc
+++ b/core/modules/field/field.views.inc
@@ -67,13 +67,8 @@ function field_views_data_alter(&$data) {
  */
 function _field_views_is_sql_entity_type(FieldInterface $field) {
   $entity_manager = \Drupal::entityManager();
-  try {
-    if ($entity_manager->getStorageController($field->entity_type) instanceof FieldableDatabaseStorageController) {
-      return TRUE;
-    }
-  }
-  catch (\InvalidArgumentException $e) {
-    // Disabled entity type, nothing to do.
+  if ($entity_manager->getDefinition($field->entity_type) && $entity_manager->getStorageController($field->entity_type) instanceof FieldableDatabaseStorageController) {
+    return TRUE;
   }
 }
 
diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php
index ef25a51..be9b370 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php
@@ -30,13 +30,6 @@
 class FieldInstanceStorageController extends ConfigStorageController {
 
   /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandler
-   */
-  protected $moduleHandler;
-
-  /**
    * The entity manager.
    *
    * @var \Drupal\Core\Entity\EntityManagerInterface
@@ -65,15 +58,12 @@ class FieldInstanceStorageController extends ConfigStorageController {
    *   The UUID service.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
-   * @param \Drupal\Core\Extension\ModuleHandler $module_handler
-   *   The module handler.
    * @param \Drupal\Core\KeyValueStore\StateInterface $state
    *   The state key value store.
    */
-  public function __construct(EntityTypeInterface $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state) {
+  public function __construct(EntityTypeInterface $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, StateInterface $state) {
     parent::__construct($entity_info, $config_factory, $config_storage, $entity_query_factory, $uuid_service);
     $this->entityManager = $entity_manager;
-    $this->moduleHandler = $module_handler;
     $this->state = $state;
   }
 
@@ -88,7 +78,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $container->get('entity.query'),
       $container->get('uuid'),
       $container->get('entity.manager'),
-      $container->get('module_handler'),
       $container->get('state')
     );
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php
index 4e79451..10db033 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php
@@ -12,7 +12,6 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldTypePluginManager;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -55,13 +54,11 @@ class FieldListController extends ConfigEntityListController {
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Field\FieldTypePluginManager $field_type_manager
    *   The 'field type' plugin manager.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, FieldTypePluginManager $field_type_manager) {
-    parent::__construct($entity_info, $entity_manager->getStorageController($entity_info->id()), $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityManagerInterface $entity_manager, FieldTypePluginManager $field_type_manager) {
+    parent::__construct($entity_info, $entity_manager->getStorageController($entity_info->id()));
 
     $this->entityManager = $entity_manager;
     $this->bundles = entity_get_bundles();
@@ -76,7 +73,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager'),
-      $container->get('module_handler'),
       $container->get('plugin.manager.field.field_type')
     );
   }
diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php
index e01e26b..3b70aea 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php
@@ -14,7 +14,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -41,13 +40,11 @@ class FilterFormatListController extends DraggableListController implements Enti
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The config factory.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ConfigFactory $config_factory) {
+    parent::__construct($entity_info, $storage);
 
     $this->configFactory = $config_factory;
   }
@@ -59,7 +56,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('config.factory')
     );
   }
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleListController.php b/core/modules/image/lib/Drupal/image/ImageStyleListController.php
index bf5618b..cce8dcf 100644
--- a/core/modules/image/lib/Drupal/image/ImageStyleListController.php
+++ b/core/modules/image/lib/Drupal/image/ImageStyleListController.php
@@ -12,7 +12,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -36,13 +35,11 @@ class ImageStyleListController extends ConfigEntityListController implements Ent
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $image_style_storage
    *   The image style entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
    *   The URL generator.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $image_style_storage, ModuleHandlerInterface $module_handler, UrlGeneratorInterface $url_generator) {
-    parent::__construct($entity_info, $image_style_storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $image_style_storage, UrlGeneratorInterface $url_generator) {
+    parent::__construct($entity_info, $image_style_storage);
     $this->urlGenerator = $url_generator;
   }
 
@@ -53,7 +50,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('url_generator'),
       $container->get('string_translation')
     );
diff --git a/core/modules/node/lib/Drupal/node/NodeListController.php b/core/modules/node/lib/Drupal/node/NodeListController.php
index b9582ae..122b97f 100644
--- a/core/modules/node/lib/Drupal/node/NodeListController.php
+++ b/core/modules/node/lib/Drupal/node/NodeListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Entity\EntityListController;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -37,13 +36,11 @@ class NodeListController extends EntityListController {
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Datetime\Date $date_service
    *   The date service.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, Date $date_service) {
+    parent::__construct($entity_info, $storage);
 
     $this->dateService = $date_service;
   }
@@ -55,7 +52,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('date')
     );
   }
diff --git a/core/modules/node/lib/Drupal/node/NodeTypeListController.php b/core/modules/node/lib/Drupal/node/NodeTypeListController.php
index 813f6ca..1549b8f 100644
--- a/core/modules/node/lib/Drupal/node/NodeTypeListController.php
+++ b/core/modules/node/lib/Drupal/node/NodeTypeListController.php
@@ -11,7 +11,6 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Component\Utility\Xss;
@@ -36,13 +35,11 @@ class NodeTypeListController extends ConfigEntityListController implements Entit
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
    *   The url generator service.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, UrlGeneratorInterface $url_generator) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, UrlGeneratorInterface $url_generator) {
+    parent::__construct($entity_info, $storage);
     $this->urlGenerator = $url_generator;
   }
 
@@ -53,7 +50,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('url_generator')
     );
   }
diff --git a/core/modules/search/lib/Drupal/search/SearchPageListController.php b/core/modules/search/lib/Drupal/search/SearchPageListController.php
index 6f86728..e7a7d8b 100644
--- a/core/modules/search/lib/Drupal/search/SearchPageListController.php
+++ b/core/modules/search/lib/Drupal/search/SearchPageListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -52,13 +51,11 @@ class SearchPageListController extends DraggableListController implements FormIn
    *   The entity storage controller class.
    * @param \Drupal\search\SearchPluginManager $search_manager
    *   The search plugin manager.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The factory for configuration objects.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, SearchPluginManager $search_manager, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, SearchPluginManager $search_manager, ConfigFactory $config_factory) {
+    parent::__construct($entity_info, $storage);
     $this->configFactory = $config_factory;
     $this->searchManager = $search_manager;
   }
@@ -71,7 +68,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
       $container->get('plugin.manager.search'),
-      $container->get('module_handler'),
       $container->get('config.factory')
     );
   }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
index 8568672..715325a 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
@@ -199,7 +199,7 @@ function testInstallConfig() {
    */
   function testEnableModulesFixedList() {
     // Install system module.
-    $this->container->get('module_handler')->install(array('system'));
+    $this->container->get('module_handler')->install(array('system', 'menu_link'));
     $entity_manager = \Drupal::entityManager();
 
     // entity_test is loaded via $modules; its entity type should exist.
diff --git a/core/modules/system/lib/Drupal/system/DateFormatListController.php b/core/modules/system/lib/Drupal/system/DateFormatListController.php
index 673730d..85d63d9 100644
--- a/core/modules/system/lib/Drupal/system/DateFormatListController.php
+++ b/core/modules/system/lib/Drupal/system/DateFormatListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -35,13 +34,11 @@ class DateFormatListController extends ConfigEntityListController {
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Datetime\Date $date_service
    *   The date service.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, Date $date_service) {
+    parent::__construct($entity_info, $storage);
 
     $this->dateService = $date_service;
   }
@@ -53,7 +50,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('date')
     );
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
index cb5ba0c..9b0295a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php
@@ -54,6 +54,6 @@ function testEntityInfoCacheWatchdog() {
     \Drupal::moduleHandler()->install(array('entity_cache_test'));
     $info = \Drupal::state()->get('entity_cache_test');
     $this->assertEqual($info->getLabel(), 'Entity Cache Test', 'Entity info label is correct.');
-    $this->assertEqual($info->getController('storage'), 'Drupal\Core\Entity\DatabaseStorageController', 'Entity controller class info is correct.');
+    $this->assertEqual($info->getStorage(), 'Drupal\Core\Entity\DatabaseStorageController', 'Entity controller class info is correct.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php
deleted file mode 100644
index 7cbe7b5..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\system\Tests\Entity\EntityManagerTest.
- */
-
-namespace Drupal\system\Tests\Entity;
-
-/**
- * Tests methods on the entity manager.
- *
- * @see \Drupal\Core\Entity\EntityManagerInterface
- */
-class EntityManagerTest extends EntityUnitTestBase {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Entity Manager',
-      'description' => 'Tests methods on the entity manager.',
-      'group' => 'Entity API',
-    );
-  }
-
-  /**
-   * Tests some methods on the manager.
-   */
-  public function testMethods() {
-    // Tests the has controller method.
-    $entity_manager = $this->container->get('entity.manager');
-    $this->assertEqual(spl_object_hash($entity_manager), spl_object_hash($this->container->get('entity.manager')));
-
-    $this->assertFalse($entity_manager->hasController('non_existent', 'storage'), 'A non existent entity type has no controller.');
-    $this->assertFalse($entity_manager->hasController('non_existent', 'non_existent'), 'A non existent entity type has no controller.');
-
-    $this->assertFalse($entity_manager->hasController('entity_test', 'non_existent'), 'An existent entity type does not have a non existent controller.');
-    $this->assertFalse($entity_manager->hasController('entity_test_mulrev', 'view_builder'), 'The test entity does not have specified the view builder.');
-
-    $this->assertTrue($entity_manager->hasController('entity_test', 'storage'), 'The test entity has specified the controller class');
-  }
-
-}
diff --git a/core/modules/user/lib/Drupal/user/Controller/UserListController.php b/core/modules/user/lib/Drupal/user/Controller/UserListController.php
index 4d2a406..a928b55 100644
--- a/core/modules/user/lib/Drupal/user/Controller/UserListController.php
+++ b/core/modules/user/lib/Drupal/user/Controller/UserListController.php
@@ -13,7 +13,6 @@
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -37,13 +36,11 @@ class UserListController extends EntityListController implements EntityControlle
    *   The entity info for the entity type.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
    *   The entity storage controller class.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
    *   The entity query factory.
    */
-  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, QueryFactory $query_factory) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, QueryFactory $query_factory) {
+    parent::__construct($entity_info, $storage);
     $this->queryFactory = $query_factory;
   }
 
@@ -54,7 +51,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
     return new static(
       $entity_info,
       $container->get('entity.manager')->getStorageController($entity_info->id()),
-      $container->get('module_handler'),
       $container->get('entity.query')
     );
   }
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php
index 066ff2a..b81fe7d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php
@@ -33,7 +33,7 @@ class DisplayPageTest extends ViewUnitTestBase {
    *
    * @var array
    */
-  public static $modules = array('system', 'user', 'menu_link', 'field');
+  public static $modules = array('system', 'user', 'menu_link', 'field', 'entity');
 
   /**
    * The router dumper to get all routes.
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
index b45efe7..363a285 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php
@@ -14,7 +14,6 @@
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -34,27 +33,24 @@ class ViewListController extends ConfigEntityListController implements EntityCon
    */
   public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
     return new static(
-      $container->get('entity.manager')->getStorageController($entity_info->id()),
       $entity_info,
-      $container->get('plugin.manager.views.display'),
-      $container->get('module_handler')
+      $container->get('entity.manager')->getStorageController($entity_info->id()),
+      $container->get('plugin.manager.views.display')
     );
   }
 
   /**
    * Constructs a new EntityListController object.
    *
-   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage.
-   *   The entity storage controller class.
    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
    *   An array of entity info for this entity type.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage.
+   *   The entity storage controller class.
    * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager
    *   The views display plugin manager to use.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
    */
-  public function __construct(EntityStorageControllerInterface $storage, EntityTypeInterface $entity_info, PluginManagerInterface $display_manager, ModuleHandlerInterface $module_handler) {
-    parent::__construct($entity_info, $storage, $module_handler);
+  public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, PluginManagerInterface $display_manager) {
+    parent::__construct($entity_info, $storage);
 
     $this->displayManager = $display_manager;
   }
diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
index d058288..534f824 100644
--- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
+++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
@@ -8,9 +8,11 @@
 namespace Drupal\views_ui\Tests;
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Tests\UnitTestCase;
 use Drupal\views\Entity\View;
 use Drupal\views\ViewExecutableFactory;
+use Drupal\views_ui\ViewListController;
 
 class ViewListControllerTest extends UnitTestCase {
 
@@ -117,18 +119,13 @@ public function testBuildRowEntityList() {
     $executable_factory = new ViewExecutableFactory($user);
     $container->set('views.executable', $executable_factory);
     $container->set('plugin.manager.views.display', $display_manager);
-    $container->set('string_translation', $this->getStringTranslationStub());
     \Drupal::setContainer($container);
 
-    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
-
     // Setup a view list controller with a mocked buildOperations method,
     // because t() is called on there.
     $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
-    $view_list_controller = $this->getMock('Drupal\views_ui\ViewListController', array('buildOperations'), array($storage_controller, $entity_type, $display_manager, $module_handler));
-    $view_list_controller->expects($this->any())
-      ->method('buildOperations')
-      ->will($this->returnValue(array()));
+    $view_list_controller = new TestViewListController($entity_type, $storage_controller, $display_manager);
+    $view_list_controller->setTranslationManager($this->getStringTranslationStub());
 
     $view = new View($values, 'view');
 
@@ -139,3 +136,11 @@ public function testBuildRowEntityList() {
   }
 
 }
+
+class TestViewListController extends ViewListController {
+
+  public function buildOperations(EntityInterface $entity) {
+    return array();
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
new file mode 100644
index 0000000..ea07604
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -0,0 +1,920 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Entity\EntityManagerTest.
+ */
+
+namespace Drupal\Tests\Core\Entity;
+
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Language\Language;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Tests the \Drupal\Core\Entity\EntityManager class.
+ *
+ * @group Drupal
+ * @group Entity
+ */
+class EntityManagerTest extends UnitTestCase {
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Tests\Core\Entity\TestEntityManager
+   */
+  protected $entityManager;
+
+  /**
+   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $discovery;
+
+  /**
+   * The dependency injection container.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $container;
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $moduleHandler;
+
+  /**
+   * The cache backend to use.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cache;
+
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManager|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $languageManager;
+
+  /**
+   * The string translationManager.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $translationManager;
+
+  /**
+   * The form builder.
+   *
+   * @var \Drupal\Core\Form\FormBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $formBuilder;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity Manager test',
+      'description' => 'Unit test the entity manager.',
+      'group' => 'Entity',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+    $this->moduleHandler->expects($this->any())
+      ->method('getImplementations')
+      ->with('entity_info')
+      ->will($this->returnValue(array()));
+
+    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+
+    $this->languageManager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->languageManager->expects($this->any())
+      ->method('getCurrentLanguage')
+      ->will($this->returnValue((object) array('id' => 'en')));
+
+    $this->translationManager = $this->getStringTranslationStub();
+
+    $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
+
+    $this->container = new ContainerBuilder();
+    $this->container->set('cache.cache', $this->cache);
+    $this->container->set('module_handler', $this->moduleHandler);
+    $this->container->set('form_builder', $this->formBuilder);
+    \Drupal::setContainer($this->container);
+
+    $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function tearDown() {
+    parent::tearDown();
+    $container = new ContainerBuilder();
+    \Drupal::setContainer($container);
+  }
+
+  /**
+   * Sets up the entity manager to be tested.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface[]|\PHPUnit_Framework_MockObject_MockObject[] $definitions
+   *   (optional) An array of entity type definitions.
+   */
+  protected function setUpEntityManager($definitions = array()) {
+    $class = $this->getMockClass('Drupal\Core\Entity\EntityInterface');
+    $definitions_map = array();
+    foreach ($definitions as $entity_type_id => $entity_type) {
+      $entity_type->expects($this->any())
+        ->method('getClass')
+        ->will($this->returnValue($class));
+      $definitions_map[] = array($entity_type_id, $entity_type);
+    }
+    $this->discovery->expects($this->any())
+      ->method('getDefinition')
+      ->will($this->returnValueMap($definitions_map));
+    $this->discovery->expects($this->any())
+      ->method('getDefinitions')
+      ->will($this->returnValue($definitions));
+
+    $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->container, $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager);
+    $this->entityManager->setDiscovery($this->discovery);
+  }
+
+  /**
+   * Tests the clearCachedDefinitions() method.
+   */
+  public function testClearCachedDefinitions() {
+    $this->setUpEntityManager();
+    $this->discovery->expects($this->once())
+      ->method('clearCachedDefinitions');
+
+    $this->entityManager->clearCachedDefinitions();
+  }
+
+  /**
+   * Tests the getDefinition() method.
+   *
+   * @dataProvider providerTestGetDefinition
+   */
+  public function testGetDefinition($entity_type_id, $expected) {
+    $entity = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $this->setUpEntityManager(array(
+      'apple' => $entity,
+      'banana' => $entity,
+    ));
+
+    $entity_type = $this->entityManager->getDefinition($entity_type_id);
+    if ($expected) {
+      $this->assertInstanceOf('Drupal\Core\Entity\EntityTypeInterface', $entity_type);
+    }
+    else {
+      $this->assertNull($entity_type);
+    }
+  }
+
+  /**
+   * Provides test data for testGetDefinition().
+   *
+   * @return array
+   *   Test data.
+   */
+  public function providerTestGetDefinition() {
+    return array(
+      array('apple', TRUE),
+      array('banana', TRUE),
+      array('pear', FALSE),
+    );
+  }
+
+  /**
+   * @expectedException \Drupal\Component\Plugin\Exception\UnknownPluginException
+   */
+  public function testGetDefinitionInvalidException() {
+    $this->setUpEntityManager();
+
+    $this->entityManager->getDefinition('pear', TRUE);
+  }
+
+  /**
+   * @dataProvider providerTestHasController
+   */
+  public function testHasController($entity_type_id, $expected) {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->any())
+      ->method('hasController')
+      ->with('storage')
+      ->will($this->returnValue(TRUE));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->any())
+      ->method('hasController')
+      ->with('storage')
+      ->will($this->returnValue(FALSE));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $entity_type = $this->entityManager->hasController($entity_type_id, 'storage');
+    $this->assertSame($expected, $entity_type);
+  }
+
+  /**
+   * Provides test data for testHasController().
+   *
+   * @return array
+   *   Test data.
+   */
+  public function providerTestHasController() {
+    return array(
+      array('apple', TRUE),
+      array('banana', FALSE),
+      array('pear', FALSE),
+    );
+  }
+
+  /**
+   * Tests the getStorageController() method.
+   */
+  public function testGetStorageController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getStorage')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityController'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityController', $this->entityManager->getStorageController('apple'));
+  }
+
+  /**
+   * Tests the getListController() method.
+   */
+  public function testGetListController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getList')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityController'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityController', $this->entityManager->getListController('apple'));
+  }
+
+  /**
+   * Tests the getViewBuilderController() method.
+   */
+  public function testGetViewBuilderController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getViewBuilder')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityController'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityController', $this->entityManager->getViewBuilder('apple'));
+  }
+
+  /**
+   * Tests the getAccessController() method.
+   */
+  public function testGetAccessController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getAccess')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityController'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityController', $this->entityManager->getAccessController('apple'));
+  }
+
+  /**
+   * Tests the getFormController() method.
+   */
+  public function testGetFormController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getForm')
+      ->with('default')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityForm'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getForm')
+      ->with('default')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityFormInjected'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $apple_form = $this->entityManager->getFormController('apple', 'default');
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityForm', $apple_form);
+    $this->assertAttributeInstanceOf('Drupal\Core\Extension\ModuleHandlerInterface', 'moduleHandler', $apple_form);
+    $this->assertAttributeInstanceOf('Drupal\Core\StringTranslation\TranslationInterface', 'translationManager', $apple_form);
+
+    $banana_form = $this->entityManager->getFormController('banana', 'default');
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityFormInjected', $banana_form);
+    $this->assertAttributeEquals('yellow', 'color', $banana_form);
+
+  }
+
+  /**
+   * Tests the getFormController() method with an invalid operation.
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+   */
+  public function testGetFormControllerInvalidOperation() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getForm')
+      ->with('banana')
+      ->will($this->returnValue(''));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+
+    $this->entityManager->getFormController('apple', 'banana');
+  }
+
+  /**
+   * Tests the getController() method.
+   */
+  public function testGetController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getController')
+      ->with('storage')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityController'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getStorage')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityControllerInjected'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $apple_controller = $this->entityManager->getController('apple', 'storage');
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityController', $apple_controller);
+    $this->assertAttributeInstanceOf('Drupal\Core\Extension\ModuleHandlerInterface', 'moduleHandler', $apple_controller);
+    $this->assertAttributeInstanceOf('Drupal\Core\StringTranslation\TranslationInterface', 'translationManager', $apple_controller);
+
+    $banana_controller = $this->entityManager->getController('banana', 'storage', 'getStorage');
+    $this->assertInstanceOf('Drupal\Tests\Core\Entity\TestEntityControllerInjected', $banana_controller);
+    $this->assertAttributeEquals('yellow', 'color', $banana_controller);
+  }
+
+  /**
+   * Tests the getController() method when no controller is defined.
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+   */
+  public function testGetControllerMissingController() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getController')
+      ->with('storage')
+      ->will($this->returnValue(''));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+    ));
+    $this->entityManager->getController('apple', 'storage');
+  }
+
+  /**
+   * Tests the getForm() method.
+   */
+  public function testGetForm() {
+    $this->formBuilder->expects($this->exactly(2))
+      ->method('buildForm')
+      ->with('the_form_id', $this->isType('array'))
+      ->will($this->returnValue('the form contents'));
+
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getForm')
+      ->with('default')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityForm'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getForm')
+      ->with('default')
+      ->will($this->returnValue('Drupal\Tests\Core\Entity\TestEntityFormInjected'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $apple_entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+    $apple_entity->expects($this->once())
+      ->method('entityType')
+      ->will($this->returnValue('apple'));
+
+    $this->assertSame('the form contents', $this->entityManager->getForm($apple_entity));
+
+    $banana_entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
+    $banana_entity->expects($this->once())
+      ->method('entityType')
+      ->will($this->returnValue('banana'));
+
+    $this->assertSame('the form contents', $this->entityManager->getForm($banana_entity));
+  }
+
+  /**
+   * Tests the getAdminRouteInfo() method.
+   */
+  public function testGetAdminRouteInfo() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getBundleEntityType')
+      ->will($this->returnValue('bundle'));
+    $banana->expects($this->once())
+      ->method('getLinkTemplate')
+      ->with('admin-form')
+      ->will($this->returnValue('entity.view'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $expected = array(
+      'route_name' => 'entity.view',
+      'route_parameters' => array(
+        'bundle' => 'chiquita',
+      ),
+    );
+    $this->assertSame($expected, $this->entityManager->getAdminRouteInfo('banana', 'chiquita'));
+    $this->assertNull($this->entityManager->getAdminRouteInfo('apple', 'delicious'));
+  }
+
+  /**
+   * Tests the getFieldDefinitions() method.
+   */
+  public function testGetFieldDefinitions() {
+    $field_definition = $this->setUpEntityWithFieldDefinition();
+
+    $expected = array('id' => $field_definition);
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type'));
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle'));
+  }
+
+  /**
+   * Tests the getFieldDefinitions() method with caching.
+   */
+  public function testGetFieldDefinitionsWithCaching() {
+    $field_definition = $this->setUpEntityWithFieldDefinition();
+
+    $expected = array('id' => $field_definition);
+
+    // @todo Investigate why this is 0 and 2, not 0/1 or 1/2.
+    $this->cache->expects($this->at(0))
+      ->method('get')
+      ->with('entity_field_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue(FALSE));
+    $this->cache->expects($this->at(2))
+      ->method('get')
+      ->with('entity_field_definitions:test_entity_type:en', FALSE)
+      ->will($this->returnValue((object) array('data' => array('definitions' => $expected))));
+
+    $this->cache->expects($this->once())
+      ->method('set');
+
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type'));
+    $this->entityManager->testClearEntityFieldInfo();
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type'));
+  }
+
+  /**
+   * Tests the getFieldDefinitions() method with bundle map.
+   */
+  public function testGetFieldDefinitionsWithBundleMap() {
+    $field_definition = $this->setUpEntityWithFieldDefinition(TRUE);
+
+    $this->moduleHandler->expects($this->at(0))
+      ->method('invokeAll')
+      ->will($this->returnValue(array()));
+    $this->moduleHandler->expects($this->at(1))
+      ->method('invokeAll')
+      ->will($this->returnValue(array(
+          'bundle map' => array(
+            'test_entity_bundle' => array(
+              'custom_field',
+            ),
+          ),
+          'optional' => array(
+            'custom_field' => $field_definition,
+          ),
+        )));
+
+    $expected = array('id' => $field_definition);
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type'));
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type', 'test_entity_type'));
+
+    $expected['custom_field'] = $field_definition;
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle'));
+  }
+
+  /**
+   * Tests the getFieldDefinitions() method with an invalid definition.
+   *
+   * @expectedException \LogicException
+   */
+  public function testGetFieldDefinitionsInvalidDefinition() {
+    $langcode_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'langcode');
+    $langcode_definition->expects($this->once())
+      ->method('isTranslatable')
+      ->will($this->returnValue(TRUE));
+
+    $this->entityManager->getFieldDefinitions('test_entity_type');
+  }
+
+  /**
+   * Tests the getFieldDefinitionsByConstraints() method.
+   */
+  public function testGetFieldDefinitionsByConstraints() {
+    $field_definition = $this->setUpEntityWithFieldDefinition();
+
+    $this->moduleHandler->expects($this->exactly(2))
+      ->method('invokeAll')
+      ->will($this->returnValue(array()));
+
+    $expected = array('id' => $field_definition);
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitionsByConstraints('test_entity_type', array()));
+    $this->assertSame($expected, $this->entityManager->getFieldDefinitionsByConstraints('test_entity_type', array('Bundle' => 'test_entity_bundle')));
+  }
+
+  /**
+   * Prepares an entity that defines a field definition.
+   *
+   * @param bool $custom_invoke_all
+   *   (optional) Whether the test will set up its own
+   *   ModuleHandlerInterface::invokeAll() implementation. Defaults to FALSE.
+   * @param string $field_definition_id
+   *   (optional) The ID to use for the field definition. Defaults to 'id'.
+   *
+   * @return \Drupal\Core\Field\FieldDefinition|\PHPUnit_Framework_MockObject_MockObject
+   *   A field definition object.
+   */
+  protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id') {
+    $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $entity = $this->getMock('Drupal\Tests\Core\Entity\TestContentEntityInterface');
+    $entity_class = get_class($entity);
+
+    $entity_type->expects($this->exactly(2))
+      ->method('getClass')
+      ->will($this->returnValue($entity_class));
+    $entity_type->expects($this->once())
+      ->method('getKeys')
+      ->will($this->returnValue(array()));
+    $field_definition = $this->getMockBuilder('Drupal\Core\Field\FieldDefinition')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $entity_class::staticExpects($this->once())
+      ->method('baseFieldDefinitions')
+      ->will($this->returnValue(array(
+        $field_definition_id => $field_definition,
+      )));
+
+    $this->moduleHandler->expects($this->once())
+      ->method('alter');
+    if (!$custom_invoke_all) {
+      $this->moduleHandler->expects($this->exactly(2))
+        ->method('invokeAll')
+        ->will($this->returnValue(array()));
+    }
+
+    $this->setUpEntityManager(array('test_entity_type' => $entity_type));
+
+    return $field_definition;
+  }
+
+  /**
+   * Tests the clearCachedFieldDefinitions() method.
+   */
+  public function testClearCachedFieldDefinitions() {
+    $this->setUpEntityManager();
+    $this->cache->expects($this->once())
+      ->method('deleteTags')
+      ->with(array('entity_field_info' => TRUE));
+
+    $this->entityManager->clearCachedFieldDefinitions();
+  }
+
+  /**
+   * Tests the getBundleInfo() method.
+   *
+   * @dataProvider providerTestGetBundleInfo
+   */
+  public function testGetBundleInfo($entity_type_id, $expected) {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Apple'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Banana'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $bundle_info = $this->entityManager->getBundleInfo($entity_type_id);
+    $this->assertSame($expected, $bundle_info);
+  }
+
+  /**
+   * Provides test data for testGetBundleInfo().
+   *
+   * @return array
+   *   Test data.
+   */
+  public function providerTestGetBundleInfo() {
+    return array(
+      array('apple', array(
+        'apple' => array(
+          'label' => 'Apple',
+        ),
+      )),
+      array('banana', array(
+        'banana' => array(
+          'label' => 'Banana',
+        ),
+      )),
+      array('pear', array()),
+    );
+  }
+
+  /**
+   * Tests the getAllBundleInfo() method.
+   */
+  public function testGetAllBundleInfo() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Apple'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Banana'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+    $this->cache->expects($this->at(1))
+      ->method('get')
+      ->will($this->returnValue(FALSE));
+    $this->cache->expects($this->at(2))
+      ->method('get')
+      ->will($this->returnValue((object) array('data' => 'cached data')));
+    $this->cache->expects($this->once())
+      ->method('set');
+
+    $expected = array(
+      'apple' => array(
+        'apple' => array(
+          'label' => 'Apple',
+        ),
+      ),
+      'banana' => array(
+        'banana' => array(
+          'label' => 'Banana',
+        ),
+      ),
+    );
+    $bundle_info = $this->entityManager->getAllBundleInfo();
+    $this->assertSame($expected, $bundle_info);
+
+    $bundle_info = $this->entityManager->getAllBundleInfo();
+    $this->assertSame($expected, $bundle_info);
+
+    $this->entityManager->clearCachedDefinitions();
+
+    $bundle_info = $this->entityManager->getAllBundleInfo();
+    $this->assertSame('cached data', $bundle_info);
+  }
+
+  /**
+   * Tests the getEntityTypeLabels() method.
+   */
+  public function testGetEntityTypeLabels() {
+    $apple = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $apple->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Apple'));
+    $banana = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $banana->expects($this->once())
+      ->method('getLabel')
+      ->will($this->returnValue('Banana'));
+    $this->setUpEntityManager(array(
+      'apple' => $apple,
+      'banana' => $banana,
+    ));
+
+    $expected = array(
+      'apple' => 'Apple',
+      'banana' => 'Banana',
+    );
+    $this->assertSame($expected, $this->entityManager->getEntityTypeLabels());
+  }
+
+  /**
+   * Tests the getTranslationFromContext() method.
+   */
+  public function testGetTranslationFromContext() {
+    $this->setUpEntityManager();
+
+    $this->languageManager->expects($this->exactly(2))
+      ->method('getFallbackCandidates')
+      ->will($this->returnCallback(function ($langcode = NULL, array $context = array()) {
+        $candidates = array();
+        if ($langcode) {
+          $candidates[$langcode] = $langcode;
+        }
+        return $candidates;
+      }));
+
+    $entity = $this->getMock('Drupal\Tests\Core\Entity\TestContentEntityInterface');
+    $entity->expects($this->exactly(2))
+      ->method('getUntranslated')
+      ->will($this->returnValue($entity));
+    $entity->expects($this->exactly(2))
+      ->method('language')
+      ->will($this->returnValue((object) array('id' => 'en')));
+    $entity->expects($this->exactly(2))
+      ->method('hasTranslation')
+      ->will($this->returnValueMap(array(
+        array(Language::LANGCODE_DEFAULT, FALSE),
+        array('custom_langcode', TRUE),
+      )));
+
+    $translated_entity = $this->getMock('Drupal\Tests\Core\Entity\TestContentEntityInterface');
+    $entity->expects($this->once())
+      ->method('getTranslation')
+      ->with('custom_langcode')
+      ->will($this->returnValue($translated_entity));
+
+    $this->assertSame($entity, $this->entityManager->getTranslationFromContext($entity));
+    $this->assertSame($translated_entity, $this->entityManager->getTranslationFromContext($entity, 'custom_langcode'));
+  }
+
+}
+
+/**
+ * Provides a testable version of ContentEntityInterface.
+ *
+ * @see https://github.com/sebastianbergmann/phpunit-mock-objects/commit/96a6794
+ */
+interface TestContentEntityInterface extends \Iterator, ContentEntityInterface {
+}
+
+/**
+ * Provides a testing version of EntityManager with an empty constructor.
+ */
+class TestEntityManager extends EntityManager {
+
+  /**
+   * Sets the discovery for the manager.
+   *
+   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
+   *   The discovery object.
+   */
+  public function setDiscovery(DiscoveryInterface $discovery) {
+    $this->discovery = $discovery;
+  }
+
+  /**
+   * Allow the $entityFieldInfo property to be cleared.
+   */
+  public function testClearEntityFieldInfo() {
+    $this->entityFieldInfo = NULL;
+  }
+
+}
+
+/**
+ * Provides a test entity controller that uses injection.
+ */
+class TestEntityControllerInjected implements EntityControllerInterface {
+
+  /**
+   * The color of the entity type.
+   *
+   * @var string
+   */
+  protected $color;
+
+  /**
+   * Constructs a new TestEntityControllerInjected.
+   *
+   * @param string $color
+   *   The color of the entity type.
+   */
+  public function __construct($color) {
+    $this->color = $color;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
+    return new static('yellow');
+  }
+
+}
+
+/**
+ * Provides a test entity form.
+ */
+class TestEntityForm extends TestEntityController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBaseFormID() {
+    return 'the_base_form_id';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'the_form_id';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setEntity(EntityInterface $entity) {
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setOperation($operation) {
+    return $this;
+  }
+
+}
+
+/**
+ * Provides a test entity form that uses injection.
+ */
+class TestEntityFormInjected extends TestEntityForm implements ContainerInjectionInterface {
+
+  /**
+   * The color of the entity type.
+   *
+   * @var string
+   */
+  protected $color;
+
+  /**
+   * Constructs a new TestEntityFormInjected.
+   *
+   * @param string $color
+   *   The color of the entity type.
+   */
+  public function __construct($color) {
+    $this->color = $color;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static('yellow');
+  }
+
+}
+
+if (!defined('DRUPAL_ROOT')) {
+  define('DRUPAL_ROOT', dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__)))));
+}
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
index 8624838..5ed6562 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
@@ -85,4 +85,109 @@ public function providerTestGetKeys() {
     );
   }
 
+  /**
+   * Tests the getController() method.
+   */
+  public function testGetController() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'storage' => $controller,
+        'form' => array(
+          'default' => $controller,
+        ),
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getController('storage'));
+    $this->assertSame($controller, $entity_type->getController('form', 'default'));
+  }
+
+  /**
+   * Tests the getStorage() method.
+   */
+  public function testGetStorage() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'storage' => $controller,
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getStorage());
+  }
+
+  /**
+   * Tests the getList() method.
+   */
+  public function testGetList() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'list' => $controller,
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getList());
+  }
+
+  /**
+   * Tests the getAccess() method.
+   */
+  public function testGetAccess() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'access' => $controller,
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getAccess());
+  }
+
+  /**
+   * Tests the getForm() method.
+   */
+  public function testGetForm() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $operation = 'default';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'form' => array(
+          $operation => $controller,
+        ),
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getForm($operation));
+  }
+
+  /**
+   * Tests the hasForms() method.
+   */
+  public function testHasForms() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $operation = 'default';
+    $entity_type1 = $this->setUpEntityType(array(
+      'controllers' => array(
+        'form' => array(
+          $operation => $controller,
+        ),
+      ),
+    ));
+    $entity_type2 = $this->setUpEntityType(array(
+      'controllers' => array(),
+    ));
+    $this->assertTrue($entity_type1->hasForms());
+    $this->assertFalse($entity_type2->hasForms());
+  }
+
+  /**
+   * Tests the getViewBuilder() method.
+   */
+  public function testGetViewBuilder() {
+    $controller = 'Drupal\Tests\Core\Entity\TestEntityController';
+    $entity_type = $this->setUpEntityType(array(
+      'controllers' => array(
+        'view_builder' => $controller,
+      ),
+    ));
+    $this->assertSame($controller, $entity_type->getViewBuilder());
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Entity/TestEntityController.php b/core/tests/Drupal/Tests/Core/Entity/TestEntityController.php
new file mode 100644
index 0000000..08e9e38
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Entity/TestEntityController.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Entity\TestEntityController.
+ */
+
+namespace Drupal\Tests\Core\Entity;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\StringTranslation\TranslationInterface;
+
+/**
+ * Provides a test entity controller.
+ */
+class TestEntityController {
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * The translation manager service.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationInterface
+   */
+  protected $translationManager;
+
+  /**
+   * Sets the module handler for this controller.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return $this
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+    return $this;
+  }
+
+  /**
+   * Sets the translation manager for this controller.
+   *
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager
+   *   The translation manager.
+   *
+   * @return $this
+   */
+  public function setTranslationManager(TranslationInterface $translation_manager) {
+    $this->translationManager = $translation_manager;
+    return $this;
+  }
+
+}
