diff --git a/core/core.services.yml b/core/core.services.yml
index 99241e4..1aae047 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -200,9 +200,26 @@ services:
     arguments: [slave]
   typed_data:
     class: Drupal\Core\TypedData\TypedDataManager
-    arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
+    arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler', '@service_container']
     calls:
       - [setValidationConstraintManager, ['@validation.constraint']]
+  typed_data_subscriber:
+    class: Drupal\Core\EventSubscriber\TypedDataSubscriber
+    arguments: ['@typed_data_resolver_manager']
+    tags:
+      - { name: event_subscriber }
+  typed_data_resolver_manager:
+    class: Drupal\Core\TypedData\Resolver\ResolverManager
+  typed_data_resolver.reflection:
+    class: Drupal\Core\TypedData\Resolver\ReflectionResolver
+    arguments: ['@typed_data']
+    tags:
+      - { name: typed_data_resolver }
+  typed_data_resolver.entity:
+    class: Drupal\Core\TypedData\Resolver\EntityResolver
+    arguments: ['@typed_data']
+    tags:
+      - { name: typed_data_resolver }
   validation.constraint:
     class: Drupal\Core\Validation\ConstraintManager
     arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
@@ -286,13 +303,20 @@ services:
       - { name: route_filter }
   paramconverter_manager:
     class: Drupal\Core\ParamConverter\ParamConverterManager
+    calls:
+      - [setContainer, ['@service_container']]
     tags:
       - { name: route_enhancer }
-  paramconverter.entity:
-    class: Drupal\Core\ParamConverter\EntityConverter
+  paramconverter_subscriber:
+    class: Drupal\Core\EventSubscriber\ParamConverterSubscriber
+    tags:
+      - { name: event_subscriber }
+    arguments: ['@paramconverter_manager']
+  paramconverter.typeddata:
+    class: Drupal\Core\ParamConverter\TypedDataConverter
     tags:
       - { name: paramconverter }
-    arguments: ['@plugin.manager.entity']
+    arguments: ['@typed_data']
   reverse_proxy_subscriber:
     class: Drupal\Core\EventSubscriber\ReverseProxySubscriber
     tags:
diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index 385f198..06a449a 100644
--- a/core/lib/Drupal/Core/Controller/ControllerResolver.php
+++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Controller;
 
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index c3b6994..ae27686 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core;
 
 use Drupal\Core\Cache\ListCacheBinsPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterTypedDataResolversPass;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass;
@@ -57,7 +58,8 @@ public function register(ContainerBuilder $container) {
     // Add a compiler pass for registering event subscribers.
     $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
     $container->addCompilerPass(new RegisterAccessChecksPass());
-    // Add a compiler pass for upcasting of entity route parameters.
+    // Add a compiler pass for upcasting route parameters.
+    $container->addCompilerPass(new RegisterTypedDataResolversPass());
     $container->addCompilerPass(new RegisterParamConvertersPass());
     $container->addCompilerPass(new RegisterRouteEnhancersPass());
     // Add a compiler pass for registering services needing destruction.
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterParamConvertersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterParamConvertersPass.php
index 6fe1447..1948727 100644
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterParamConvertersPass.php
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterParamConvertersPass.php
@@ -23,26 +23,14 @@ class RegisterParamConvertersPass implements CompilerPassInterface {
    *   The container to process.
    */
   public function process(ContainerBuilder $container) {
-
     if (!$container->hasDefinition('paramconverter_manager')) {
       return;
     }
 
     $manager = $container->getDefinition('paramconverter_manager');
-
-    $services = array();
     foreach ($container->findTaggedServiceIds('paramconverter') as $id => $attributes) {
       $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
-
-      $services[$priority][] = new Reference($id);
-    }
-
-    krsort($services);
-
-    foreach ($services as $priority) {
-      foreach ($priority as $service) {
-        $manager->addMethodCall('addConverter', array($service));
-      }
+      $manager->addMethodCall('addConverter', array($id, $priority));
     }
   }
 }
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTypedDataResolversPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTypedDataResolversPass.php
new file mode 100644
index 0000000..53e8b33
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTypedDataResolversPass.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\DependencyInjection\Compiler\RegisterTypedDataResolversPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Registers typed data resolver services with the typed data resolver manager.
+ */
+class RegisterTypedDataResolversPass implements CompilerPassInterface {
+
+  /**
+   * Register typed data resolver services with the typed data resolver manager.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container to process.
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('typed_data_resolver_manager')) {
+      return;
+    }
+
+    $manager = $container->getDefinition('typed_data_resolver_manager');
+    foreach ($container->findTaggedServiceIds('typed_data_resolver') as $id => $attributes) {
+      $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
+      $manager->addMethodCall('addTypeDataResolver', array(new Reference($id), $priority));
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index 33a62ce..77f3975 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -13,6 +13,7 @@
 use Drupal\Core\TypedData\TypedDataInterface;
 use IteratorAggregate;
 use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a base entity class.
@@ -77,6 +78,26 @@ public function __construct(array $values, $entity_type) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public static function load($id, array $definition, ContainerInterface $container) {
+    $entity_type = substr($definition['type'], strlen('entity:'));
+    $bundle = NULL;
+    if (strpos(':', $entity_type) !== FALSE) {
+      list($entity_type, $bundle) = explode($entity_type, 2);
+    }
+
+    if (!$storage = $container->get('plugin.manager.entity')->getStorageController($entity_type)) {
+      throw new \InvalidArgumentException(sprintf('Could not retrieve storage controller for the %s entity type', $entity_type));
+    }
+
+    $entity = $storage->load($id);
+    if ($entity && (!isset($bundle) || $entity->bundle() == $bundle)) {
+      return $entity;
+    }
+  }
+
+  /**
    * Implements \Drupal\Core\Entity\EntityInterface::id().
    */
   public function id() {
diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
index a3ffcb9..f0b0c92 100644
--- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
+++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides backwards compatible (BC) access to entity fields.
@@ -68,6 +69,13 @@ function __construct(EntityNG $decorated, array &$definitions) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public static function load($id, array $definition, ContainerInterface $container) {
+    return Entity::load($id, $definition, $container);
+  }
+
+  /**
    * Overrides Entity::getNGEntity().
    */
   public function getNGEntity() {
diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php
index e965b8e..c4a4488 100644
--- a/core/lib/Drupal/Core/Entity/EntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityInterface.php
@@ -10,6 +10,7 @@
 use Drupal\Core\TypedData\AccessibleInterface;
 use Drupal\Core\TypedData\ComplexDataInterface;
 use Drupal\Core\TypedData\IdentifiableInterface;
+use Drupal\Core\TypedData\LoadableInterface;
 use Drupal\Core\TypedData\TranslatableInterface;
 
 /**
@@ -28,7 +29,7 @@
  * @see \Drupal\Core\TypedData\TypedDataManager
  * @see \Drupal\Core\Field\FieldInterface
  */
-interface EntityInterface extends IdentifiableInterface, ComplexDataInterface, AccessibleInterface, TranslatableInterface {
+interface EntityInterface extends IdentifiableInterface, ComplexDataInterface, AccessibleInterface, TranslatableInterface, LoadableInterface {
 
   /**
    * Returns the entity UUID (Universally Unique Identifier).
diff --git a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
new file mode 100644
index 0000000..1afff6c
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\EventSubscriber\ParamConverterSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Drupal\Core\ParamConverter\ParamConverterManager;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Drupal\Core\Routing\RoutingEvents;
+use Drupal\Core\Routing\RouteBuildEvent;
+
+/**
+ * Event subscriber for registering parameter converters with routes.
+ */
+class ParamConverterSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The parameter converter manager.
+   *
+   * @var \Drupal\Core\ParamConverter\ParamConverterManager
+   */
+  protected $paramConverterManager;
+
+  /**
+   * Constructs a new ParamConverterSubscriber.
+   *
+   * @param \Drupal\Core\ParamConverter\ParamConverterManager $param_converter_manager
+   *   The parameter converter manager that will be responsible for upcasting
+   *   request attributes.
+   */
+  public function __construct(ParamConverterManager $param_converter_manager) {
+    $this->paramConverterManager = $param_converter_manager;
+  }
+
+  /**
+   * Applies parameter converters to route parameters.
+   *
+   * @param \Drupal\Core\Routing\RouteBuildEvent $event
+   *   The event to process.
+   */
+  public function onRoutingRouteAlterSetParameterConverters(RouteBuildEvent $event) {
+    $this->paramConverterManager->setRouteParameterConverters($event->getRouteCollection());
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetParameterConverters', 10);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/TypedDataSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/TypedDataSubscriber.php
new file mode 100644
index 0000000..9b05d6b
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/TypedDataSubscriber.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\EventSubscriber\TypedDataSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Drupal\Core\TypedData\Resolver\ResolverManager;
+use Drupal\Core\TypedData\TypedDataDetector;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Drupal\Core\Routing\RoutingEvents;
+use Drupal\Core\Routing\RouteBuildEvent;
+
+/**
+ * Typed data subscriber for route build events.
+ */
+class TypedDataSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The typed data resolver.
+   *
+   * @var \Drupal\Core\TypedData\Resolver\ResolverManager
+   */
+  protected $resolverManager;
+
+  /**
+   * Constructs a TypedDataSubscriber object.
+   */
+  public function __construct(ResolverManager $resolver_manager) {
+    $this->resolverManager = $resolver_manager;
+  }
+
+  /**
+   * Generates typed data definition for route arguments.
+   *
+   * @param \Drupal\Core\Routing\RouteBuildEvent $event
+   *   The event to process.
+   */
+  public function onRoutingRouteAlterSetAccessCheck(RouteBuildEvent $event) {
+    $this->resolverManager->resolveParameterTypes($event->getRouteCollection());
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    // Setting very low priority to ensure typed data discovery runs after
+    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetAccessCheck', 20);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
deleted file mode 100644
index 50b7d7c..0000000
--- a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\Core\ParamConverter\EntityConverter.
- */
-
-namespace Drupal\Core\ParamConverter;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Drupal\Core\Entity\EntityManager;
-
-/**
- * This class allows the upcasting of entity ids to the respective entity
- * object.
- */
-class EntityConverter implements ParamConverterInterface {
-
-  /**
-   * Entity manager which performs the upcasting in the end.
-   *
-   * @var \Drupal\Core\Entity\EntityManager
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a new EntityConverter.
-   *
-   * @param \Drupal\Core\Entity\EntityManager $entityManager
-   *   The entity manager.
-   */
-  public function __construct(EntityManager $entityManager) {
-    $this->entityManager = $entityManager;
-  }
-
-  /**
-   * Tries to upcast every variable to an entity type.
-   *
-   * If there is a type denoted in the route options it will try to upcast to
-   * it, if there is no definition in the options it will try to upcast to an
-   * entity type of that name. If the chosen enity type does not exists it will
-   * leave the variable untouched.
-   * If the entity type exist, but there is no entity with the given id it will
-   * convert the variable to NULL.
-   *
-   * Example:
-   *
-   * pattern: '/a/{user}/some/{foo}/and/{bar}/'
-   * options:
-   *   converters:
-   *     foo: 'node'
-   *
-   * The value for {user} will be converted to a user entity and the value
-   * for {foo} to a node entity, but it will not touch the value for {bar}.
-   *
-   * It will not process variables which are marked as converted. It will mark
-   * any variable it processes as converted.
-   *
-   * @param array &$variables
-   *   Array of values to convert to their corresponding objects, if applicable.
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route object.
-   * @param array &$converted
-   *   Array collecting the names of all variables which have been
-   *   altered by a converter.
-   */
-  public function process(array &$variables, Route $route, array &$converted) {
-    $variable_names = $route->compile()->getVariables();
-
-    $options = $route->getOptions();
-    $configuredTypes = isset($options['converters']) ? $options['converters'] : array();
-
-    $entityTypes = array_keys($this->entityManager->getDefinitions());
-
-    foreach ($variable_names as $name) {
-      // Do not process this variable if it's already marked as converted.
-      if (in_array($name, $converted)) {
-        continue;
-      }
-
-      // Obtain entity type to convert to from the route configuration or just
-      // use the variable name as default.
-      if (array_key_exists($name, $configuredTypes)) {
-        $type = $configuredTypes[$name];
-      }
-      else {
-        $type = $name;
-      }
-
-      if (in_array($type, $entityTypes)) {
-        $value = $variables[$name];
-
-        $storageController = $this->entityManager->getStorageController($type);
-        $entity = $storageController->load($value);
-        $variables[$name] = $entity;
-
-        // Mark this variable as converted.
-        $converted[] = $name;
-      }
-    }
-  }
-}
diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php
index 74307c2..5f4bd4f 100644
--- a/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php
+++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\ParamConverter;
 
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Route;
 
 /**
@@ -17,13 +18,34 @@
   /**
    * Allows to convert variables to their corresponding objects.
    *
-   * @param array &$variables
-   *   Array of values to convert to their corresponding objects, if applicable.
+   * @param mixed $definition
+   *   The parameter definition provided in the route options.
+   * @param string $name
+   *   The name of the parameter.
+   * @param array $defaults
+   *   The route defaults array.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object.
+   *
+   * @return mixed
+   *   The converted parameter value.
+   */
+  public function convert($definition, $name, array $defaults, Request $request);
+
+  /**
+   * Determines if the converter applies to a specific route and variable.
+   *
+   * @param mixed $definition
+   *   The parameter definition provided in the route options.
+   * @param string $name
+   *   The name of the parameter.
    * @param \Symfony\Component\Routing\Route $route
-   *   The route object.
-   * @param array &$converted
-   *   Array collecting the names of all variables which have been
-   *   altered by a converter.
+   *   The route to consider attaching to.
+   *
+   * @return bool
+   *   TRUE if the converter applies to the passed route and parameter, FALSE
+   *   otherwise.
    */
-  public function process(array &$variables, Route $route, array &$converted);
+  public function applies($definition, $name, Route $route);
+
 }
diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
index be5676e..74d6206 100644
--- a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
+++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
@@ -7,14 +7,13 @@
 
 namespace Drupal\Core\ParamConverter;
 
-use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\Routing\RouteCollection;
 use Symfony\Component\HttpFoundation\Request;
 
-use Drupal\Core\ParamConverter\ParamConverterInterface;
-
 /**
  * Provides a service which allows to enhance (say alter) the arguments coming
  * from the URL.
@@ -24,66 +23,166 @@
  * This class will not enhance any of the arguments itself, but allow other
  * services to register to do so.
  */
-class ParamConverterManager implements RouteEnhancerInterface {
+class ParamConverterManager extends ContainerAware implements RouteEnhancerInterface {
 
   /**
-   * Converters managed by the ParamConverterManager.
+   * An array of registered converter service ids.
    *
    * @var array
    */
-  protected $converters;
+  protected $converterIds = array();
 
   /**
-   * Adds a converter to the paramconverter service.
+   * Array of registered converter service ids sorted by their priority.
    *
-   * @see \Drupal\Core\DependencyInjection\Compiler\RegisterParamConvertersPass
+   * @var array
+   */
+  protected $sortedConverterIds;
+
+  /**
+   * Array of loaded converter services keyed by their ids.
    *
-   * @param \Drupal\Core\ParamConverter\ParamConverterInterface $converter
-   *   The converter to add.
+   * @var array
    */
-  public function addConverter(ParamConverterInterface $converter) {
-    $this->converters[] = $converter;
+  protected $converters = array();
+
+
+  /**
+   * Registers a parameter converter with the manager.
+   *
+   * @param string $converter
+   *   The parameter converter service id to register.
+   * @param int $priority
+   *   (optional) The priority of the converter. Defaults to 0.
+   *
+   * @return \Drupal\Core\ParamConverter\ParamConverterManager
+   *   The called object for chaining.
+   */
+  public function addConverter($converter, $priority = 0) {
+    $converter = substr($converter, strlen('paramconverter.'));
+    if (empty($this->converterIds[$priority])) {
+      $this->converterIds[$priority] = array();
+    }
+    $this->converterIds[$priority][] = $converter;
+    unset($this->sortedConverterIds);
     return $this;
   }
 
   /**
-   * Implements \Symfony\Cmf\Component\Routing\Enhancer\ŖouteEnhancerIterface.
+   * Sorts the converter service ids and flattens them.
+   *
+   * @return array
+   *   The sorted parameter converter servide ids.
+   */
+  public function getConverterIds() {
+    if (!isset($this->sortedConverterIds)) {
+      krsort($this->converterIds);
+      $this->sortedConverterIds = array();
+      foreach ($this->converterIds as $resolvers) {
+        $this->sortedConverterIds = array_merge($this->sortedConverterIds, $resolvers);
+      }
+    }
+    return $this->sortedConverterIds;
+  }
+
+  /**
+   * For each route, saves a list of applicable converters to the route.
    *
-   * Iterates over all registered converters and allows them to alter the
-   * defaults.
+   * @param \Symfony\Component\Routing\RouteCollection $routes
+   *   A collection of routes to apply converters to.
+   */
+  public function setRouteParameterConverters(RouteCollection $routes) {
+    foreach ($routes as $route) {
+      if (!$parameters = $route->getOption('parameters') ?: array()) {
+        // Continue with the next route if no parameters have been defined.
+        continue;
+      }
+
+      // Loop over all defined parameters and look up the right converter.
+      foreach ($parameters as $name => &$definition) {
+        if (isset($definition['converter'])) {
+          // Skip parameters that already have a manually set converter.
+          continue;
+        }
+
+        foreach ($this->getConverterIds() as $converter) {
+          if ($this->getConverter($converter)->applies($definition, $name, $route)) {
+            $definition['converter'] = $converter;
+          }
+        }
+      }
+
+      // Override the parameters array.
+      $route->setOption('parameters', $parameters);
+    }
+  }
+
+  /**
+   * Invokes the registered converter for each defined parameter on a route.
    *
    * @param array $defaults
-   *   The getRouteDefaults array.
+   *   The route defaults array.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The current request.
    *
+   * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+   *   If a variable has been converted to NULL.
+   *
    * @return array
    *   The modified defaults.
    */
   public function enhance(array $defaults, Request $request) {
-    // This array will collect the names of all variables which have been
-    // altered by a converter.
-    // This serves two purposes:
-    // 1. It might prevent converters later in the pipeline to process
-    //    a variable again.
-    // 2. To check if upcasting was successfull after each converter had
-    //    a go. See below.
-    $converters = array();
-
     $route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
 
-    foreach ($this->converters as $converter) {
-      $converter->process($defaults, $route, $converters);
+    // Skip this enhancer if there are no parameter definitions.
+    if (!$parameters = $route->getOption('parameters') ?: array()) {
+      return $defaults;
     }
 
-    // Check if all upcasting yielded a result.
-    // If an upcast value is NULL do a 404.
-    foreach ($converters as $variable) {
-      if ($defaults[$variable] === NULL) {
+    // Invoke the registered converter for each parameter.
+    foreach ($parameters as $parameter => $definition) {
+      if (array_key_exists($parameter, $defaults) && $defaults[$parameter] === NULL) {
+        // Do not try to convert anything that is already set to NULL.
+        continue;
+      }
+
+      if (!isset($definition['converter'])) {
+        // Continue if no converter has been specified.
+        continue;
+      }
+
+      // If a converter returns NULL it means that the parameter could not be
+      // converted in which case we throw a 404.
+      $defaults[$parameter] = $this->getConverter($definition['converter'])->convert($definition, $parameter, $defaults, $request);
+      if (!isset($defaults[$parameter])) {
         throw new NotFoundHttpException();
       }
     }
 
     return $defaults;
   }
+
+  /**
+   * Lazy-loads converter services.
+   *
+   * @param string $converter
+   *   The service id of converter service to load.
+   *
+   * @return \Drupal\Core\ParamConverter\ParamConverterInterface
+   *   The loaded converter service identified by the given service id.
+   *
+   * @throws \InvalidArgumentException
+   *   If the given service id is not a registered converter.
+   */
+  protected function getConverter($converter) {
+    if (isset($this->converters[$converter])) {
+      return $this->converters[$converter];
+    }
+    if (!in_array($converter, $this->getConverterIds())) {
+      throw new \InvalidArgumentException(sprintf('No converter has been registered for %s', $converter));
+    }
+    return $this->converters[$converter] = $this->container->get("paramconverter.$converter");
+  }
+
 }
+
diff --git a/core/lib/Drupal/Core/ParamConverter/TypedDataConverter.php b/core/lib/Drupal/Core/ParamConverter/TypedDataConverter.php
new file mode 100644
index 0000000..2c6feea
--- /dev/null
+++ b/core/lib/Drupal/Core/ParamConverter/TypedDataConverter.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\ParamConverter\TypedDataConverter.
+ */
+
+namespace Drupal\Core\ParamConverter;
+
+use Drupal\Component\Plugin\Context\Context;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Route;
+use Drupal\Core\TypedData\TypedDataManager;
+
+/**
+ * Upcasts request attributes to typed data objects.
+ */
+class TypedDataConverter implements ParamConverterInterface {
+
+  /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManager
+   */
+  protected $typedDataManager;
+
+  /**
+   * Constructs a new TypedDataConverter object.
+   *
+   * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager
+   *   The typed data manager.
+   */
+  public function __construct(TypedDataManager $typed_data_manager) {
+    $this->typedDataManager = $typed_data_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function convert($definition, $name, array $defaults, Request $request) {
+    // Only continue if there is a value for the given parameter.
+    if (!isset($defaults[$name])) {
+      return;
+    }
+
+    // Remove keys that do not belong to the typed data definition.
+    unset($definition['converter']);
+
+    // Allow per-data definition overrides of the used classes, i.e. take over
+    // classes specified in the data definition.
+    $original = $this->typedDataManager->getDefinition($definition['type']);
+    $key = empty($definition['list']) ? 'class' : 'list class';
+    if (isset($definition[$key])) {
+      $class = $definition[$key];
+    }
+    elseif (isset($original[$key])) {
+      $class = $original[$key];
+    }
+
+    // If the given typed data type is not loadable, just create an instance.
+    if (!is_subclass_of($class, 'Drupal\Core\TypedData\LoadableInterface')) {
+      return $this->typedDataManager->create($definition, $defaults[$name]);
+    }
+
+    // Try to load the typed data object via the typed data manager.
+    return $this->typedDataManager->load($defaults[$name], $definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies($definition, $name, Route $route) {
+    return !empty($definition['type']) && $this->typedDataManager->getDefinition($definition['type']);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/LoadableInterface.php b/core/lib/Drupal/Core/TypedData/LoadableInterface.php
new file mode 100644
index 0000000..0405256
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/LoadableInterface.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains LoadableInterface.
+ */
+
+namespace Drupal\Core\TypedData;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Interface for loadable typed data objects.
+ */
+interface LoadableInterface {
+
+  /**
+   * Loads a typed data object.
+   *
+   * @param mixed $id
+   *   The unique identifier of the typed data object to be loaded.
+   * @param array $definition
+   *   The typed data definition.
+   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   *   The service container this object should use.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface|null
+   *   The loaded typed data object or NULL if it could not be loaded.
+   */
+  public static function load($id, array $definition, ContainerInterface $container);
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/Resolver/EntityResolver.php b/core/lib/Drupal/Core/TypedData/Resolver/EntityResolver.php
new file mode 100644
index 0000000..228bcf0
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/Resolver/EntityResolver.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\TypedData\Resolver\EntityResolver.
+ */
+
+namespace Drupal\Core\TypedData\Resolver;
+
+use Drupal\Core\TypedData\TypedDataManager;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Generates typed data definitions for specific entity routes.
+ */
+class EntityResolver implements ResolverInterface {
+
+  /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManager;
+   */
+  protected $typedDataManager;
+
+  /**
+   * Constructs a EntityResolver object.
+   *
+   * @param TypedDataManager $typed_data_manager
+   *   The typed data manager to use.
+   */
+  public function __construct(TypedDataManager $typed_data_manager) {
+    $this->typedDataManager = $typed_data_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resolveParameterTypes(Route $route) {
+    $defaults = $route->getDefaults();
+    if (!empty($defaults['_controller'])) {
+      return;
+    }
+
+    // Either the '_entity_form' or '_entity_list' have to be set.
+    if (empty($defaults['_entity_form']) && empty($defaults['_entity_list'])) {
+      return;
+    }
+
+    // This typed data resolver is only capable of generating typed data
+    // definitions for routes that have either '_entity_form' or '_entity_list'
+    // in the route defaults array.
+    $entity_type = NULL;
+    if (!empty($defaults['_entity_form'])) {
+      list ($entity_type) = explode('.', $defaults['_entity_form']);
+    }
+    elseif (!empty($defaults['_entity_list'])) {
+      $entity_type = $defaults['_entity_list'];
+    }
+
+    // Check if there is a variable that matches the provided entity type.
+    if (!in_array($entity_type, $route->compile()->getVariables())) {
+      return;
+    }
+
+    // Return the typed data definition for the given entity type if it exists.
+    if ($this->typedDataManager->getDefinition("entity:$entity_type")) {
+      return array($entity_type => array(
+        'type' => "entity:$entity_type",
+      ));
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/Resolver/ReflectionResolver.php b/core/lib/Drupal/Core/TypedData/Resolver/ReflectionResolver.php
new file mode 100644
index 0000000..9bd2b28
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/Resolver/ReflectionResolver.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\TypedData\Resolver\ReflectionResolver.
+ */
+
+namespace Drupal\Core\TypedData\Resolver;
+
+use Drupal\Core\TypedData\TypedDataManager;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Generates typed data definitions based on a controller's type hints.
+ */
+class ReflectionResolver implements ResolverInterface {
+
+  /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManager;
+   */
+  protected $typedDataManager;
+
+  /**
+   * Constructs a ReflectionResolver object.
+   *
+   * @param TypedDataManager $typed_data_manager
+   *   The typed data manager to use.
+   */
+  public function __construct(TypedDataManager $typed_data_manager) {
+    $this->typedDataManager = $typed_data_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resolveParameterTypes(Route $route) {
+    $defaults = $route->getDefaults();
+
+    // Iterate over all entries in the defaults array to find any callable
+    // that might have type hints from which we can draw clues.
+    $definitions = array();
+    foreach ($defaults as $default) {
+      if (is_string($default) && strpos($default, '::') !== FALSE) {
+        list($class, $method) = explode('::', $default, 2);
+        if (!class_exists($class)) {
+          throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+        }
+
+        $callable = array($class, $method);
+        if ($parameters = $this->getParameterTypes($callable)) {
+          $definitions = array_merge($parameters, $definitions);
+        }
+      }
+    }
+
+    return $definitions;
+  }
+
+  /**
+   * Tries to determine the typed data types via the type hints on a callable.
+   *
+   * @param mixed $callable
+   *   A callable.
+   *
+   * @return array
+   *   An array of typed data definitions keyed by parameter name.
+   */
+  protected function getParameterTypes($callable) {
+    if (is_array($callable)) {
+      $reflection = new \ReflectionMethod($callable[0], $callable[1]);
+    }
+    elseif (is_object($callable) && !$callable instanceof \Closure) {
+      $reflection = new \ReflectionObject($callable);
+      $reflection = $reflection->getMethod('__invoke');
+    }
+    else {
+      $reflection = new \ReflectionFunction($callable);
+    }
+
+    $definitions = array();
+    foreach ($reflection->getParameters() as $parameter) {
+      $definitions[$parameter->getName()] = $this->getParameterType($parameter);
+    }
+    return $definitions;
+  }
+
+  /**
+   * Tries to determine the typed data type of a given parameter.
+   *
+   * @param \ReflectionParameter $parameter
+   *   The parameter to generate a typed data definition for.
+   *
+   * @return array
+   *   The typed data definition for the given parameter.
+   */
+  protected function getParameterType(\ReflectionParameter $parameter) {
+    if (!$class = $parameter->getClass()) {
+      // The parameter does not have a proper type hint.
+      return;
+    }
+
+    // Ignore request object type hints.
+    $name = $class->getName();
+    $request = 'Symfony\Component\HttpFoundation\Request';
+    if ($name == $request || $class->isSubclassOf($request)) {
+      return;
+    }
+
+    // Try to find a typed data type that matches the type hint.
+    foreach ($this->typedDataManager->getDefinitions() as $type => $definition) {
+      if ($definition['class'] == $class) {
+        // Return the first match.
+        return $definition;
+      }
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/Resolver/ResolverInterface.php b/core/lib/Drupal/Core/TypedData/Resolver/ResolverInterface.php
new file mode 100644
index 0000000..9b63eb6
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/Resolver/ResolverInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\TypedData\Resolver\ResolverInterface.
+ */
+
+namespace Drupal\Core\TypedData\Resolver;
+
+use Symfony\Component\Routing\Route;
+
+/**
+ * Interface for typed data definition resolvers.
+ */
+interface ResolverInterface {
+
+  /**
+   * Tries to generate typed data definitions for the parameters of a route.
+   *
+   * @param Route $route
+   *   The route object for which to generate typed data definitions.
+   *
+   * @return array
+   *   An array of typed data definitions keyed by parameter name.
+   */
+  public function resolveParameterTypes(Route $route);
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/Resolver/ResolverManager.php b/core/lib/Drupal/Core/TypedData/Resolver/ResolverManager.php
new file mode 100644
index 0000000..cf21b47
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/Resolver/ResolverManager.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\TypedData\Resolver\ResolverManager.
+ */
+
+namespace Drupal\Core\TypedData\Resolver;
+
+use Drupal\Core\TypedData\TypedDataManager;
+use ReflectionMethod;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Generates typed data definitions for route parameters.
+ */
+class ResolverManager {
+
+  /**
+   * An array of registered typed data resolvers.
+   *
+   * @var array
+   */
+  protected $resolvers = array();
+
+  /**
+   * Array of registered typed resolvers sorted by their priority.
+   *
+   * @var array
+   */
+  protected $sortedResolvers;
+
+  /**
+   * Registers a typed data resolver with the manager.
+   *
+   * @param \Drupal\Core\TypedData\Resolver\ResolverInterface $resolver
+   *   The typed data resolver to register.
+   * @param int $priority
+   *   (optional) The priority of the typed data resolver. Defaults to 0.
+   *
+   * @return \Drupal\Core\TypedData\Resolver\ResolverManager
+   *   The called object for chaining.
+   */
+  public function addTypeDataResolver(ResolverInterface $resolver, $priority = 0) {
+    if (empty($this->resolvers[$priority])) {
+      $this->resolvers[$priority] = array();
+    }
+    $this->resolvers[$priority][] = $resolver;
+    unset($this->sortedResolvers);
+    return $this;
+  }
+
+  /**
+   * Sorts the resolvers and flattens them.
+   *
+   * @return array
+   *   The sorted typed data resolvers.
+   */
+  public function getTypedDataResolvers() {
+    if (!isset($this->sortedResolvers)) {
+      krsort($this->resolvers);
+      $this->sortedResolvers = array();
+      foreach ($this->resolvers as $resolvers) {
+        $this->sortedResolvers = array_merge($this->sortedResolvers, $resolvers);
+      }
+    }
+    return $this->sortedResolvers;
+  }
+
+  /**
+   * Tries to generate typed data definitions for each route in a collection.
+   *
+   * @param RouteCollection $routes
+   *   A route collection.
+   */
+  public function resolveParameterTypes(RouteCollection $routes) {
+    $resolvers = $this->getTypedDataResolvers();
+    foreach ($routes->all() as $route) {
+      $definitions = array();
+      foreach ($resolvers as $resolver) {
+        if ($parameters = $resolver->resolveParameterTypes($route)) {
+          $definitions = array_merge($parameters, $definitions);
+        }
+      }
+
+      // Merge the resolved typed data definitions into the route options.
+      if (!empty($definitions)) {
+        // Do not override manually defined typed data definitions.
+        $definitions = array_merge($definitions, ($route->getOption('parameters') ?: array()));
+        $route->setOption('parameters', $definitions);
+      }
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataConverter.php b/core/lib/Drupal/Core/TypedData/TypedDataConverter.php
new file mode 100644
index 0000000..bb11a76
--- /dev/null
+++ b/core/lib/Drupal/Core/TypedData/TypedDataConverter.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\TypedData\TypedDataConverter.
+ */
+
+namespace Drupal\Core\TypedData;
+
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Class TypedDataConverter
+ * @package Drupal\Core\TypedData
+ */
+class TypedDataConverter implements ParamConverterInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function process(array &$variables, Route $route, array &$converted) {
+    $parameters = $route->getOption('parameters') ?: array();
+    foreach ($parameters as $parameter => $options) {
+
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
index 5c48fb0..89a0ddd 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\TypedData;
 
 use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManager;
@@ -16,13 +17,15 @@
 use Drupal\Core\TypedData\Validation\MetadataFactory;
 use Drupal\Core\Validation\ConstraintManager;
 use Drupal\Core\Validation\DrupalTranslator;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Validator\ValidatorInterface;
 use Symfony\Component\Validator\Validation;
 
 /**
  * Manages data type plugins.
  */
-class TypedDataManager extends DefaultPluginManager {
+class TypedDataManager extends DefaultPluginManager implements ContainerAwareInterface {
 
   /**
    * The validator used for validating typed data.
@@ -45,7 +48,14 @@ class TypedDataManager extends DefaultPluginManager {
    */
   protected $prototypes = array();
 
-  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler) {
+  /**
+   * The container.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerInterface
+   */
+  protected $container;
+
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler, ContainerInterface $container) {
     $this->alterInfo($module_handler, 'data_type_info');
     $this->setCacheBackend($cache_backend, $language_manager, 'typed_data:types');
 
@@ -53,6 +63,14 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
       'Drupal\Core\TypedData\Annotation' => DRUPAL_ROOT . '/core/lib',
     );
     parent::__construct('DataType', $namespaces, $annotation_namespaces, 'Drupal\Core\TypedData\Annotation\DataType');
+    $this->container = $container;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContainer(ContainerInterface $container = NULL) {
+    $this->container = $container;
   }
 
   /**
@@ -382,4 +400,48 @@ public function getConstraints($definition) {
     }
     return $constraints;
   }
+
+  /**
+   * Loads a typed data object by its id.
+   *
+   * @param $id
+   *   The unique identifier of the typed data object to be loaded.
+   * @param array $definition
+   *   The data definition array.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   *   If no instance class was given.
+   * @throws \InvalidArgumentException
+   *   If the given instance class does not implement the LoadableInterface.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface|null
+   *   The loaded typed data object or NULL if it could not be loaded.
+   */
+  public function load($id, array $definition) {
+    $original_definition = $this->discovery->getDefinition($definition['type']);
+    if (!isset($original_definition)) {
+      throw new \InvalidArgumentException(String::format('Invalid data type (%plugin) has been given.', array('%plugin' => $definition['type'])));
+    }
+
+    // Allow per-data definition overrides of the used classes, i.e. take over
+    // classes specified in the data definition.
+    $key = empty($definition['list']) ? 'class' : 'list class';
+    if (isset($definition[$key])) {
+      $class = $definition[$key];
+    }
+    elseif (isset($original_definition[$key])) {
+      $class = $original_definition[$key];
+    }
+
+    if (!isset($class)) {
+      throw new PluginException(String::format('The plugin %plugin did not specify an instance class.', array('%plugin' => $definition['type'])));
+    }
+
+    // The instance class has to implement the LoadableInterface.
+    if (!in_array('Drupal\Core\TypedData\LoadableInterface', class_implements($class))) {
+      throw new \InvalidArgumentException('The given class has to implement the LoadableInterface.');
+    }
+
+    return $class::load($id, $definition, $this->container);
+  }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
index 3558d20..4b76fdc 100644
--- a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
@@ -614,4 +614,21 @@ public function testTypedDataValidation() {
     $this->assertEqual($violations[0]->getInvalidValue(), 'string');
     $this->assertIdentical($violations[0]->getPropertyPath(), '0.value');
   }
+
+  /**
+   * Tests loading of typed data objects that implement LoadableInterface.
+   */
+  public function testTypedDataLoading() {
+    // Generate a file for testing typed data loading.
+    file_unmanaged_copy(DRUPAL_ROOT . '/core/misc/druplicon.png', 'public://example.png');
+    $image = entity_create('file', array('uri' => 'public://example.png'));
+    $image->save();
+
+    $loaded = \Drupal::typedData()->load($image->id(), array(
+      'type' => 'entity:file',
+    ));
+
+    $this->assertNotIdentical(FALSE, $loaded, 'Successfully loaded the image entity.');
+    $this->assertIdentical($image->uuid(), $loaded->uuid(), 'Successfully loaded the right image entity..');
+  }
 }
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index 92fa27b..140891f 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views_ui;
 
+use Drupal\Core\Entity\Entity;
 use Drupal\views\Views;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\views\ViewExecutable;
@@ -16,6 +17,7 @@
 use Drupal\views\Plugin\views\query\Sql;
 use Drupal\views\Plugin\Core\Entity\View;
 use Drupal\views\ViewStorageInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Stores UI related temporary settings.
@@ -1243,4 +1245,11 @@ public function mergeDefaultDisplaysOptions() {
   public function uriRelationships() {
     return $this->storage->uriRelationships();
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function load($id, array $definition, ContainerInterface $container) {
+    return Entity::load($id, $definition, $container);
+  }
 }
