diff --git a/MultifieldEntityController.php b/MultifieldEntityController.php
index 62ae5f2..28ddcc7 100644
--- a/MultifieldEntityController.php
+++ b/MultifieldEntityController.php
@@ -57,7 +57,7 @@ class MultifieldEntityController extends DrupalDefaultEntityController {
           foreach ($entities as $entity) {
             if ($items = field_get_items($entity_type, $entity, $field_name)) {
               foreach ($items as $item) {
-                $pseudo_entities[$item['id']] = _multifield_field_item_to_entity($field['type'], $item);
+                $pseudo_entities[$item['id']] = _multifield_field_item_to_entity(multifield_extract_multifield_machine_name(field_info_field($field_name)), $item);
               }
             }
           }
diff --git a/multifield.field.inc b/multifield.field.inc
index a10305d..05cf95e 100644
--- a/multifield.field.inc
+++ b/multifield.field.inc
@@ -34,6 +34,8 @@ function multifield_field_info() {
       'hide_blank_items' => TRUE,
       'entity_translation_sync' => array('id'),
     ),
+    'property_type' => 'multifield',
+    'property_callbacks' => array('multifield_field_property_callback'),
   );
 
   // Deprecated field types from the CTools exports.
@@ -59,6 +61,65 @@ function multifield_field_info() {
 }
 
 /**
+ * Property callback for the Entity Metadata framework.
+ */
+function multifield_field_property_callback(&$info, $entity_type, $field, $instance, $field_type) {
+  $instance['property info'] = array(
+    'getter callback' => 'multifield_field_property_get',
+    'setter callback' => 'multifield_field_property_set',
+    'raw getter callback' => 'multifield_field_property_get_raw',
+  );
+  // Then apply the default.
+  entity_metadata_field_default_property_callback($info, $entity_type, $field, $instance, $field_type);
+  unset($info['query callback']);
+}
+
+/**
+ * Callback for getting field property values.
+ */
+function multifield_field_property_get($entity, array $options, $name, $entity_type, $info) {
+  $field = field_info_field($name);
+  $langcode = isset($options['language']) ? $options['language']->language : LANGUAGE_NONE;
+  $langcode = entity_metadata_field_get_language($entity_type, $entity, $field, $langcode, TRUE);
+  $values = array();
+  if (isset($entity->{$name}[$langcode])) {
+    foreach ($entity->{$name}[$langcode] as $delta => $data) {
+      $multifield_entity = _multifield_field_item_to_entity(multifield_extract_multifield_machine_name($field), $data);
+      $values[$delta] = $multifield_entity->id;
+    }
+  }
+  // For an empty single-valued field, we have to return NULL.
+  return $field['cardinality'] == 1 ? ($values ? reset($values) : NULL) : $values;
+}
+
+/**
+ * Callback for getting raw field property values.
+ */
+function multifield_field_property_get_raw($entity, array $options, $name, $entity_type, $info) {
+  $field = field_info_field($name);
+  $langcode = isset($options['language']) ? $options['language']->language : LANGUAGE_NONE;
+  $langcode = entity_metadata_field_get_language($entity_type, $entity, $field, $langcode, TRUE);
+  $values = isset($entity->{$name}[$langcode]) ? $entity->{$name}[$langcode] : array();
+  // For an empty single-valued field, we have to return NULL.
+  return $field['cardinality'] == 1 ? ($values ? reset($values) : NULL) : $values;
+}
+
+/**
+ * Callback for setting field property values.
+ */
+function multifield_field_property_set($entity, $name, $value, $langcode, $entity_type, $info) {
+  $field = field_info_field($name);
+  $columns = array_keys($field['columns']);
+  $langcode = entity_metadata_field_get_language($entity_type, $entity, $field, $langcode);
+  $values = $field['cardinality'] == 1 ? array($value) : (array) $value;
+
+  $entity->{$name}[$langcode] = $values;
+  // Empty the static field language cache, so the field system picks up any
+  // possible new languages.
+  drupal_static_reset('field_language');
+}
+
+/**
  * Implements hook_field_settings_form().
  */
 function multifield_field_settings_form($field, $instance) {
diff --git a/multifield.module b/multifield.module
index fa3a1c6..9ebf98a 100644
--- a/multifield.module
+++ b/multifield.module
@@ -112,6 +112,7 @@ function multifield_entity_info() {
       'id' => 'id',
       'bundle' => 'type',
     ),
+    'access callback' => 'multifield_access_callback',
   );
 
   // Bundles must provide a human readable name so we can create help and error
@@ -131,6 +132,34 @@ function multifield_entity_info() {
   return $info;
 }
 
+/**
+ * Access callback for entity access.
+ */
+function multifield_access_callback($op, $entity, $account, $entity_type) {
+  // If there is no multifield entity there is no host entity we can check. In
+  // that situation, grant access.
+  if (empty($entity)) {
+    return TRUE;
+  }
+  // The field name is the bundle of the multifield entity.
+  list($multifield_id, , $field_name) = entity_extract_ids($entity_type, $entity);
+  $field = field_info_field($field_name);
+
+  // Find out the entity and entity type for the host entity.
+  $field_column = _field_sql_storage_columnname($field_name, 'id');
+  $field_table = _field_sql_storage_tablename($field);
+  $host_entity_info = db_query('SELECT entity_type, entity_id FROM {' . $field_table . '} WHERE ' . $field_column . ' = :entity_id', array(
+    ':entity_id' => $multifield_id,
+  ))->fetch();
+  if (!$host_entity_info) {
+    // If the host entity could not be found, then deny access.
+    return FALSE;
+  }
+  $host_entities = entity_load($host_entity_info->entity_type, array($host_entity_info->entity_id));
+  $host_entity = reset($host_entities);
+  return field_access($op, $field, $host_entity_info->entity_type, $host_entity, $account);
+}
+
 function multifield_load($name) {
   $result = multifield_load_all();
   return isset($result[$name]) ? $result[$name] : FALSE;
