diff --git a/render_cache.module b/render_cache.module
index 6640c69..2015c09 100644
--- a/render_cache.module
+++ b/render_cache.module
@@ -31,7 +31,7 @@ function render_cache_entity_view_callback($entities, $view_mode, $langcode = NU
   // Setup drupal_render style cache array.
   $cache_info = render_cache_cache_info_defaults();
   $cache_info['keys'] = array(
-    'render_cache',
+    'entity',
     $entity_type,
     $view_mode,
   );
@@ -235,7 +235,7 @@ function render_cache_cache_info_defaults() {
 }
 
 /**
- * Retrieve cache ID to use for render caching.
+ * Retrieve cache ID to use for entity render caching.
  *
  * @param object $entity
  *   The entity object being rendered.
@@ -259,7 +259,7 @@ function render_cache_get_entity_cid($entity, &$cache_info, $context) {
   }
 
   $cache_info += render_cache_cache_info_defaults();
-  
+
   drupal_alter('render_cache_entity_cache_info', $cache_info, $entity, $context);
 
   $cid_parts = array();
@@ -323,7 +323,7 @@ function render_cache_flush_caches() {
  *
  * @param $entity_type
  *   The type of the entity.
- * $parem $entity
+ * $param $entity
  *   The entity to render.
  * $param $view_mode
  *   A view mode as used by this entity type, e.g. 'full', 'teaser'...
@@ -352,3 +352,200 @@ function node_render_cache_entity_hash_alter(&$hash, $entity, $cache_info, $cont
     $hash['node_comment_count'] = $entity->comment_count;
   }
 }
+
+/**
+ * Helper function to view a single entity field.
+ *
+ * This can be used to replace field_view_field().
+ *
+ * @param string $entity_type
+ *   The type of $entity; e.g., 'node' or 'user'.
+ * @param object $entity
+ *   The entity containing the field to display. Must at least contain the id
+ *   key and the field data to display.
+ * @param string $field_name
+ *   The name of the field to display.
+ * @param string|array $display
+ *   Can be either:
+ *   - The name of a view mode. The field will be displayed according to the
+ *     display settings specified for this view mode in the $instance
+ *     definition for the field in the entity's bundle.
+ *     If no display settings are found for the view mode, the settings for
+ *     the 'default' view mode will be used.
+ *   - An array of display settings, as found in the 'display' entry of
+ *     $instance definitions. The following key/value pairs are allowed:
+ *     - label: (string) Position of the label. The default 'field' theme
+ *       implementation supports the values 'inline', 'above' and 'hidden'.
+ *       Defaults to 'above'.
+ *     - type: (string) The formatter to use. Defaults to the
+ *       'default_formatter' for the field type, specified in
+ *       hook_field_info(). The default formatter will also be used if the
+ *       requested formatter is not available.
+ *     - settings: (array) Settings specific to the formatter. Defaults to the
+ *       formatter's default settings, specified in
+ *       hook_field_formatter_info().
+ *     - weight: (float) The weight to assign to the renderable element.
+ *       Defaults to 0.
+ * @param string $langcode
+ *   (Optional) The language the field values are to be shown in. The site's
+ *   current language fallback logic will be applied no values are available
+ *   for the language. If no language is provided the current language will be
+ *   used.
+ *
+ * @return
+ *   A renderable array for the field value.
+ */
+function render_cache_view_field($entity_type, $entity, $field_name, $display = array(), $langcode = NULL) {
+  // If the entity has no field value, just return nothing.
+  $items = field_get_items($entity_type, $entity, $field_name);
+  if (empty($items)) {
+    return array();
+  }
+
+  // Prepare context
+  $context = array(
+    'entity_type' => $entity_type,
+    'field_name' => $field_name,
+    'display' => $display,
+    'langcode' => field_language($entity_type, $entity, $field_name, $langcode),
+    'deltas' => array_keys($items),
+  );
+
+  // Setup drupal_render style cache array.
+  $cache_info = render_cache_cache_info_defaults();
+  $cache_info['keys'] = array(
+    'field',
+    $entity_type,
+    $field_name,
+  );
+
+  drupal_alter('render_cache_field_default_cache_info', $cache_info, $context);
+
+  list($entity_id, $entity_revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
+  $entity_context = $context + array(
+    'entity_id' => $entity_id,
+    'entity_revision_id' => $entity_revision_id,
+    'bundle' => $bundle,
+  );
+  $cid = render_cache_get_field_cid($entity, $cache_info, $entity_context);
+  $cache = cache_get($cid, 'cache_render');
+
+  if (!$cache) {
+    $field_render = field_view_field($entity_type, $entity, $field_name, $display, $langcode);
+    if (isset($cache_info['granularity']) && $cache_info['granularity'] != DRUPAL_NO_CACHE) {
+      if (empty($cache_info['render_cache_render_to_markup'])) {
+        cache_set($cid, $field_render, 'cache_render');
+      }
+      else {
+        // Process markup with drupal_render() caching.
+        $field_render['#cache'] = $cache_info;
+
+        // Explicitly set cache id.
+        $field_render['#cache']['cid'] = $cid;
+
+        $render_cache_attached = array();
+        // Preserve some properties in #attached?
+        if (!empty($cache_info['render_cache_render_to_markup']['preserve properties']) &&
+          is_array($cache_info['render_cache_render_to_markup']['preserve properties'])) {
+          foreach ($cache_info['render_cache_render_to_markup']['preserve properties'] as $key) {
+            if (isset($field_render[$key])) {
+              $render_cache_attached[$key] = $field_render[$key];
+            }
+          }
+        }
+        if (!empty($render_cache_attached)) {
+          $field_render['#attached']['render_cache'] = $render_cache_attached;
+        }
+
+        // Do we want to render now?
+        if (empty($cache_info['render_cache_render_to_markup']['cache late'])) {
+          // And save things. Also add our preserved properties back.
+          $field_render = array(
+            '#markup' => drupal_render($field_render),
+          ) + $render_cache_attached;
+        }
+      }
+    }
+
+    $cache = (object) array(
+      'data' => $field_render,
+    );
+  }
+
+  $render = $cache->data;
+
+  // Potentially merge back previously saved properties.
+  if (!empty($render['#attached']['render_cache'])) {
+    $render += $render['#attached']['render_cache'];
+    unset($render['#attached']['render_cache']);
+  }
+
+  // Run any post-render callbacks.
+  // @todo Not sure what should be used for the second parameter here?
+  render_cache_process_attached_callbacks($render, $cid);
+
+  return $render;
+}
+
+/**
+ * Retrieve cache ID to use for field render caching.
+ *
+ * @param object $entity
+ *   The entity object being rendered.
+ * @param array $cache_info
+ *   A drupal_render style cache array().
+ * @param array $context
+ *   The context of the field, with the following keys:
+ *   - entity_type
+ *   - entity_id
+ *   - entity_revision_id
+ *   - bundle
+ *   - langcode
+ *   - field_name
+ *   - display
+ *   - deltas
+ *
+ * @return string
+ */
+function render_cache_get_field_cid($entity, &$cache_info, $context) {
+  if (isset($cache_info['cid'])) {
+    return $cache_info['cid'];
+  }
+
+  $cache_info += render_cache_cache_info_defaults();
+
+  drupal_alter('render_cache_field_cache_info', $cache_info, $entity, $context);
+
+  $cid_parts = array('field');
+  $hash = array();
+
+  if (!empty($cache_info['keys']) && is_array($cache_info['keys'])) {
+    $cid_parts = $cache_info['keys'];
+  }
+
+  // Add drupal_render cid_parts based on granularity
+  $granularity = isset($cache_info['granularity']) ? $cache_info['granularity'] : NULL;
+  $cid_parts = array_merge($cid_parts, drupal_render_cid_parts($granularity));
+
+  // Calculate hash to expire cached items automatically.
+  $hash['id'] = !empty($context['entity_revision_id']) ? $context['entity_revision_id'] : $context['entity_id'];
+  $hash['bundle'] = !empty($context['bundle']) ? $context['bundle'] : $context['entity_type'];
+  $hash['modified'] = entity_modified_last($context['entity_type'], $entity);
+  $hash['render_method'] = !empty($cache_info['render_cache_render_to_markup']);
+  if ($hash['render_method']) {
+    $hash['render_options'] = serialize($cache_info['render_cache_render_to_markup']);
+  }
+
+  // Generally hash per display - its unlikely they are the same.
+  $hash['deltas'] = implode(',', $context['deltas']);
+  $hash['display'] = serialize($context['display']);
+  $hash['langcode'] = $context['langcode'];
+
+  // Allow modules to modify $hash for custom invalidating.
+  drupal_alter('render_cache_field_hash', $hash, $entity, $cache_info, $context);
+
+  $cid_parts[] = sha1(implode('-', $hash));
+  drupal_alter('render_cache_field_cid', $cid_parts, $entity, $cache_info, $context);
+
+  return implode(':', $cid_parts);
+}
