diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index c1abfe5..3df9ba6 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -56,6 +56,17 @@ class CoreBundle extends Bundle
       ->addArgument('slave');
     $container->register('typed_data', 'Drupal\Core\TypedData\TypedDataManager');
 
+    $container->register('paramconverter_manager', 'Drupal\Core\ParamConverter\ParamConverterManager')
+      ->addMethodCall('setContainer', array(new Reference('service_container')));
+
+    $container->register('paramconverter.subscriber', 'Drupal\Core\EventSubscriber\ParamConverterSubscriber')
+      ->addArgument(new Reference('paramconverter_manager'));
+
+    $container->register('paramconverter.entity', 'Drupal\Core\ParamConverter\EntityConverter');
+
+    $container->getDefinition('paramconverter_manager')
+      ->addMethodCall('addConverterService', array('paramconverter.entity', 'Drupal\node\Node'));
+
     $container->register('router.dumper', '\Drupal\Core\Routing\MatcherDumper')
       ->addArgument(new Reference('database'));
     $container->register('router.builder', 'Drupal\Core\Routing\RouteBuilder')
@@ -73,11 +84,14 @@ class CoreBundle extends Bundle
     $nested->setFinalMatcher(new \Drupal\Core\Routing\FirstEntryFinalMatcher());
     $matcher->add($nested, 5);
 
+    $dispatcher->addSubscriberService('paramconverter.subscriber', 'Drupal\Core\EventSubscriber\ParamConverterSubscriber');
+
     $content_negotation = new \Drupal\Core\ContentNegotiation();
     $dispatcher->addSubscriber(new \Symfony\Component\HttpKernel\EventListener\RouterListener($matcher));
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\ViewSubscriber($content_negotation));
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\AccessSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\MaintenanceModeSubscriber());
+    //$dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\ParamConverterSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\PathSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyRequestSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyControllerSubscriber());
diff --git a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
new file mode 100644
index 0000000..6854e32
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\EventSubscriber\MParamConverterSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Drupal\Core\ParamConverter\ParamConverterManager;
+
+/**
+ * Handles converting request attributes to their appropriate objects.
+ */
+class ParamConverterSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Broker object that handles actually converting parameters.
+   *
+   * @var \Drupal\Core\ParamConverter\ParamConverterManager
+   */
+  protected $paramConverterManager;
+
+  /**
+   * Constructs a new ParamConverterSubscriber.
+   *
+   * @param ParamConverterManager $param_converter_manager
+   *   The converter manager that will be responsible for converting
+   *   request attributes into their corresponding object values.
+   */
+  public function __construct(ParamConverterManager $param_converter_manager) {
+    $this->paramConverterManager = $param_converter_manager;
+  }
+
+  /**
+   * Response with the maintenance page when the site is offline.
+   *
+   * @param Symfony\Component\HttpKernel\Event\FilterControllerEvent $event
+   *   The Event to process.
+   */
+  public function onKernelControllerParamConverter(FilterControllerEvent $event) {
+    $request = $event->getRequest();
+
+    // If this is a legacy request, skip it as we're not doing conversion for
+    // those.
+    // @todo Remove this check once we eliminate the legacy router.
+    if ($request->attributes->has('drupal_menu_item')) {
+      return;
+    }
+
+    $controller = $event->getController();
+
+    $this->paramConverterManager->applyToRequest($controller, $request);
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::CONTROLLER][] = array('onKernelControllerParamConverter', 40);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
new file mode 100644
index 0000000..f31842c
--- /dev/null
+++ b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\ParamConverter\EntityConverter.
+ */
+
+namespace Drupal\Core\ParamConverter;
+
+/**
+ * Parameter converter for entities.
+ *
+ * Each entity type needs to be reistered on ParamConverterManager
+ * independently, but all entities can use this same converter.
+ */
+class EntityConverter implements ParamConverterInterface {
+
+  /**
+   * Constructs a new EntityConverter.
+   *
+   * This is awful, full stop.  This should all be happening via an injected
+   * entity factory. But, that's not feasible yet because those are not in the
+   * Service Container.
+   *
+   * @todo Refactor this to not suck when the entity system is properly
+   *   injectable.  Then provide proper unit tests.
+   */
+  public function __construct() {
+    $entity_info = entity_get_info();
+
+    foreach ($entity_info as $entity_type => $info) {
+      $info['entity_type'] = $entity_type;
+      $this->entities[$info['entity class']] = $info;
+    }
+
+  }
+
+  /**
+   * Implements ParamConverterInterface::convert().
+   */
+  public function convert($value, $class, array $arguments = array()) {
+    // If we don't know about the class we're being asked to convert to, do
+    // nothing.
+    if (empty($this->entities[$class])) {
+      throw new \InvalidArgumentException(sprintf('No entity found that uses class %s', $class));
+    }
+
+    $info = $this->entities[$class];
+
+    // Load the entity loader, then use it to load the object.
+    // Once again, this should be coming from the Service Container eventually.
+    $loader = new $info['controller class']($info['entity_type']);
+
+    $entities = $loader->load(array($value));
+    return reset($entities);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php
new file mode 100644
index 0000000..1077fd6
--- /dev/null
+++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\ParamConverter\ParamConverterInterface.
+ */
+
+namespace Drupal\Core\ParamConverter;
+
+/**
+ * Interface for parameter converters.
+ */
+interface ParamConverterInterface {
+
+  /**
+   * Converts the provided value to an object of type $class.
+   *
+   * @param mixed $value
+   *   The value to upcast to an object.
+   * @param string $class
+   *   The fully qualified name of the class to convert to.
+   * @param array $arguments
+   *   (optional) An array of arguments to direct the converter how to behave.
+   *     These values will vary with the converter.
+   */
+   public function convert($value, $class, array $arguments = array());
+}
diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
new file mode 100644
index 0000000..953acfb
--- /dev/null
+++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\ParamConverter\ParamConverterManager.
+ */
+
+namespace Drupal\Core\ParamConverter;
+
+use Symfony\Component\DependencyInjection\ContainerAware;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * This class manages conversion of request attributes to typed objects.
+ */
+class ParamConverterManager extends ContainerAware {
+
+  /**
+   * Array of Converter services to apply.
+   *
+   * The array keys are fully qualified class names; The value is an associative
+   * array containing service_id (the ID of the container service that provides
+   * the corresponding converter) and arguments, which is an associative array
+   * of options to pass to the converter at conversion time.
+   *
+   * @var array
+   */
+  protected $converterIds;
+
+  /**
+   * Array of instantiated converter objects.
+   *
+   * The array keys are full qualified class names; the values are the
+   * instantiated converter object.
+   *
+   * @var array
+   */
+  protected $converters;
+
+  /**
+   * Registers a new converter by servie ID.
+   *
+   * @param string $service_id
+   *   The ID of the service in the Container that provides a converter.
+   * @param string $classname
+   *   The fully qualified class name that should use this converter.
+   * @param array $arguments
+   *   (optional) An array of arguments that should be passed to the converter
+   *   on invocation.
+   */
+  public function addConverterService($service_id, $classname, array $arguments = array()) {
+    $this->converterIds[$classname] = array(
+      'service_id' => $service_id,
+      'arguments' => $arguments,
+    );
+  }
+
+  /**
+   * Converts all request attributes based on type hints on the Controller.
+   *
+   * @param callable $controller
+   *   The controller that is to be called.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object to convert.
+   */
+  public function applyToRequest($controller, Request $request) {
+    if (is_array($controller)) {
+      $r = new \ReflectionMethod($controller[0], $controller[1]);
+    }
+    else {
+      $r = new \ReflectionFunction($controller);
+    }
+
+    foreach ($r->getParameters() as $param) {
+      // Only process parameters that are type-hinted and not the Request
+      // object, since that's already covered by the ControllerResolver.
+      if (!$param->getClass() || $param->getClass()->isInstance($request)) {
+        continue;
+      }
+
+      $param_name = $param->getName();
+
+      $new_value = $this->convertTo($request->attributes->get($param_name), $param->getClass()->getName());
+      $request->attributes->set($param_name, $new_value);
+    }
+  }
+
+  /**
+   * Converts a value to the specified classname.
+   *
+   * @param mixed $value
+   *   The value to convert.  It may be of any type other than object.
+   * @param string $classname
+   *   The fully qualified name of the class to which to convert the value.
+   *
+   * @return object
+   *   An object of type $classname, based on $value.
+   */
+  public function convertTo($value, $classname) {
+    if (empty($this->converters[$classname])) {
+      $this->loadConverter($classname);
+    }
+
+    return $this->converters[$classname]->convert($value, $classname, $this->converterIds[$classname]['arguments']);
+  }
+
+  /**
+   * Instantiates a converter based on the provided class.
+   *
+   * @param string $classname
+   *   The fully qualified name of the class for which to load the converter.
+   */
+  protected function loadConverter($classname) {
+    if (empty($this->converterIds[$classname])) {
+      throw new \InvalidArgumentException(sprintf('No converter has been registered for %s.', $classname));
+    }
+    $info = $this->converterIds[$classname];
+    $this->converters[$classname] = $this->container->get($info['service_id']);
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockConverter.php b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockConverter.php
new file mode 100644
index 0000000..9fe147a
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockConverter.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\ParamConverter\MockConverter.
+ */
+
+namespace Drupal\system\Tests\ParamConverter;
+
+use Symfony\Component\HttpFoundation\Request;
+
+use Drupal\simpletest\UnitTestBase;
+use Drupal\Core\ParamConverter\ParamConverterManager;
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+
+/**
+ * Fake ParamConverter for testing.
+ */
+class MockConverter implements ParamConverterInterface {
+
+  public function convert($value, $class, array $arguments = array()) {
+     return new MockType($value);
+   }
+
+}
+
diff --git a/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockType.php b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockType.php
new file mode 100644
index 0000000..3044f05
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/MockType.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\ParamConverter\MockConverter.
+ */
+
+namespace Drupal\system\Tests\ParamConverter;
+
+
+/**
+ * Fake class for testing.
+ */
+class MockType {
+
+  public $id;
+
+  public function __construct($id) {
+    $this->id = $id;
+  }
+
+}
+
diff --git a/core/modules/system/lib/Drupal/system/Tests/ParamConverter/ParamConverterManagerTest.php b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/ParamConverterManagerTest.php
new file mode 100644
index 0000000..a1ea1a8
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/ParamConverter/ParamConverterManagerTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\ParamConverter\ParamConverterManagerTest.
+ */
+
+namespace Drupal\system\Tests\ParamConverter;
+
+use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+
+use Drupal\simpletest\UnitTestBase;
+use Drupal\Core\ParamConverter\ParamConverterManager;
+
+/**
+ * Basic tests for the ChainMatcher.
+ */
+class ParamConverterManagerTest extends UnitTestBase {
+
+  /**
+   * A simple container for testing purposes.
+   *
+   * @var \Drupal\Core\DependencyInjection\ContainerBuilder
+   */
+  protected $mockContainer;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'ParamConverter Manager tests',
+      'description' => 'Confirm that the ParamConverterMatcher is working correctly.',
+      'group' => 'Routing',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->mockContainer = new ContainerBuilder();
+    $this->mockContainer->register('test_converter', 'Drupal\system\Tests\ParamConverter\MockConverter');
+  }
+
+  /**
+   * Confirms that a parameter is converted when expected.
+   */
+  public function testParamConverted() {
+
+    $converter = new ParamConverterManager();
+    $converter->setContainer($this->mockContainer);
+    $converter->addConverterService('test_converter', 'Drupal\system\Tests\ParamConverter\MockType');
+
+    $request = Request::create('/foo/{bar}');
+    $request->attributes->set('bar', 1);
+
+    $controller = function (MockType $bar) {};
+
+    $converter->applyToRequest($controller, $request);
+
+    $this->assertTrue($request->attributes->get('bar') instanceof MockType, 'The parameter was upcast successfully.');
+  }
+
+  /**
+   * Confirms that un-hinted parameters are not affected.
+   */
+  public function testParamNoConversionNeeded() {
+
+    $converter = new ParamConverterManager();
+    $converter->setContainer($this->mockContainer);
+    $converter->addConverterService('test_converter', 'Drupal\system\Tests\ParamConverter\MockType');
+
+    $request = Request::create('/foo/{bar}/{baz}');
+    $request->attributes->set('bar', 1);
+    $request->attributes->set('baz', 2);
+
+    $controller = function (MockType $bar, $baz) {};
+
+    $converter->applyToRequest($controller, $request);
+
+    $this->assertTrue($request->attributes->get('bar') instanceof MockType, 'hinted parameter was upcast successfully.');
+    $this->assertEqual($request->attributes->get('baz'), 2, 'Bare parameter was not changed.');
+  }
+
+  /**
+   * Confirms that if a parameter is not convertable an exceptoin is thrown.
+   */
+  public function testNoTypeRegistered() {
+
+    $converter = new ParamConverterManager();
+    $converter->setContainer($this->mockContainer);
+
+    $request = Request::create('/foo/{bar}');
+    $request->attributes->set('bar', 1);
+
+    $controller = function (MockType $bar) {};
+
+    try {
+      $converter->applyToRequest($controller, $request);
+    }
+    catch (\InvalidArgumentException $e) {
+      $this->pass('InvalidArgumentException thrown for an unregistered type.');
+      return;
+    }
+
+    $this->fail('No exceptoin thrown for unregisterd type.');
+  }
+
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/ParamConverterTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/ParamConverterTest.php
new file mode 100644
index 0000000..5123a53
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Routing/ParamConverterTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\ParamConverterTest.
+ */
+
+namespace Drupal\system\Tests\Routing;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Basic tests for the ChainMatcher.
+ */
+class ParamConverterTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('block', 'router_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Parameter Conversion tests',
+      'description' => 'Function Tests for parameter conversion.',
+      'group' => 'Routing',
+    );
+  }
+
+  /**
+   * Confirms that we can successfully use a route with converted parameter.
+   */
+  public function testCanRoute() {
+
+    $title = $this->randomString();
+
+    $node = $this->drupalCreateNode(array(
+      'title' => $title,
+    ));
+
+    $this->drupalGet('router_test/test6/' . $node->id());
+    $this->assertRaw($title, 'The correct node title was found, and there were no fatal errors.');
+  }
+
+}
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php
new file mode 100644
index 0000000..aa49d88
--- /dev/null
+++ b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Drupal\router_test;
+
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+
+use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Scope;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+
+/**
+ * Bundle class for the Router Test module.
+ */
+class RouterTestBundle extends Bundle {
+  public function build(ContainerBuilder $container) {
+
+  }
+}
+
+class TestParamConverter implements ParamConverterInterface {
+
+  /**
+   *
+   * @param mixed $value
+   *   The value to upcast to an object
+   * @param string $class
+   *   The fully qualified name of the class to convert to.
+   * @param array $arguments
+   *   (optional) An array of arguments to direct the converter how to behave.
+   *     These values will vary with the converter.
+   */
+  public function convert($value, $class, array $arguments = array()) {
+
+
+  }
+
+}
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
index fa92fd8..532a73a 100644
--- a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
+++ b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
@@ -8,6 +8,7 @@
 namespace Drupal\router_test;
 
 use Symfony\Component\HttpFoundation\Response;
+use Drupal\node\Node;
 
 /**
  * Controller routines for testing the routing system.
@@ -30,4 +31,9 @@ class TestControllers {
     return $value;
   }
 
+  public function test6(Node $node) {
+    // If $node isn't a Node object, PHP will fatal for us already before
+    // we get here.
+    return $node->label();
+  }
 }
diff --git a/core/modules/system/tests/modules/router_test/router_test.info b/core/modules/system/tests/modules/router_test/router_test.info
index d729865..2660ca1 100644
--- a/core/modules/system/tests/modules/router_test/router_test.info
+++ b/core/modules/system/tests/modules/router_test/router_test.info
@@ -3,4 +3,4 @@ description = "Support module for routing testing."
 package = Testing
 version = VERSION
 core = 8.x
-hidden = TRUE
+;hidden = TRUE
diff --git a/core/modules/system/tests/modules/router_test/router_test.module b/core/modules/system/tests/modules/router_test/router_test.module
index 4da939d..621e447 100644
--- a/core/modules/system/tests/modules/router_test/router_test.module
+++ b/core/modules/system/tests/modules/router_test/router_test.module
@@ -30,5 +30,10 @@ function router_test_route_info() {
   ));
   $collection->add('router_test_4', $route);
 
+  $route = new Route('router_test/test6/{node}', array(
+    '_controller' => '\Drupal\router_test\TestControllers::test6',
+  ));
+  $collection->add('router_test_6', $route);
+
   return $collection;
 }
