diff --git a/product/ERP5Type/mixin/component.py b/product/ERP5Type/mixin/component.py
index 996bba5358e4af8e164ddf8aa9f02030a0cc5157..fd1ca0bfff6b501c212b7c88469ceb3b25c2c4b8 100644
--- a/product/ERP5Type/mixin/component.py
+++ b/product/ERP5Type/mixin/component.py
@@ -40,7 +40,91 @@ from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
 
 from zLOG import LOG, INFO
 
+_recorded_property_name_tuple = (
+  'reference',
+  'version',
+  'text_content')
+
+from ExtensionClass import ExtensionClass
+from Products.ERP5Type.Utils import convertToUpperCase
+
+class RecordablePropertyMetaClass(ExtensionClass):
+  """
+  Meta-class for extension classes with registered setters and getters wrapped
+  to respectively record and get property through PropertyRecordableMixin
+  """
+  def __new__(metacls, name, bases, dictionary):
+    def setterWrapper(accessor_name, property_name):
+      dictionary['security'].declareProtected(Permissions.ModifyPortalContent,
+                                              accessor_name)
+
+      def setter(self, property_value):
+        """
+        Everytime either 'reference', 'version' or 'text_content' are modified
+        when a Component is in modified or validated state, the Component is
+        set to modified state by component interaction workflow, then in this
+        method, the current property value is recorded in order to handle any
+        error returned when checking consistency before the new value is
+        set. At the end, through component interaction workflow, the Component
+        is validated only if checkConsistency returns no error
+
+        The recorded property will be used upon loading the Component whereas
+        the new value set is displayed in Component view.
+        """
+        if self.getValidationState() in ('modified', 'validated'):
+          self.recordProperty(property_name)
+
+        return getattr(super(ComponentMixin, self), accessor_name)(property_value)
+
+      setter.__name__ = accessor_name
+      return setter
+
+    def getterWrapper(accessor_name, property_name):
+      dictionary['security'].declareProtected(Permissions.AccessContentsInformation,
+                                              accessor_name)
+
+      def getter(self, validated_only=False):
+        """
+        When validated_only is True, then returns the property recorded if
+        the Component has been modified but there was an error upon
+        consistency checking
+        """
+        if validated_only:
+          try:
+            return self.getRecordedProperty(property_name)
+          # AttributeError when this property has never been recorded before
+          # (_recorded_property_dict) and KeyError if the property has been
+          # recorded before but is not anymore
+          except (AttributeError, KeyError):
+            pass
+
+        return getattr(super(ComponentMixin, self), accessor_name)()
+
+      getter.__name__ = accessor_name
+      return getter
+
+    for property_name in _recorded_property_name_tuple:
+      setter_name = '_set' + convertToUpperCase(property_name)
+      dictionary[setter_name] = setterWrapper(setter_name, property_name)
+
+      getter_name = 'get' + convertToUpperCase(property_name)
+      dictionary[getter_name] = getterWrapper(getter_name, property_name)
+
+    # docstring required for publishing any object
+    dictionary['__doc__'] = metacls.__doc__
+
+    # ExtensionClass required to avoid metaclasses conflicts when
+    # ghosting/unghosting Portal Types
+    new_class = ExtensionClass.__new__(ExtensionClass,
+                                       name,
+                                       bases,
+                                       dictionary)
+
+    return new_class
+
 class ComponentMixin(PropertyRecordableMixin, Base):
+  __metaclass__ = RecordablePropertyMetaClass
+
   isPortalContent = 1
   isRADContent = 1
   isDelivery = ConstantGetter('isDelivery', value=True)
@@ -129,37 +213,6 @@ class ComponentMixin(PropertyRecordableMixin, Base):
 
     return error_list
 
-  def _recordPropertyDecorator(accessor_name, property_name):
-    def inner(self, property_value):
-      """
-      Everytime either 'reference', 'version' or 'text_content' are
-      modified when a Component is in modified or validated state, the
-      Component is set to modified state by component interaction
-      workflow, then in this method, the current property value is
-      recorded in order to handle any error returned when checking
-      consistency before the new value is set. At the end, through
-      component interaction workflow, the Component is validated only
-      if checkConsistency returns no error
-
-      The recorded property will be used upon loading the Component
-      whereas the new value set is displayed in Component view.
-      """
-      if self.getValidationState() in ('modified', 'validated'):
-        self.recordProperty(property_name)
-
-      return getattr(super(ComponentMixin, self), accessor_name)(property_value)
-
-    return inner
-
-  security.declareProtected(Permissions.ModifyPortalContent, '_setReference')
-  _setReference = _recordPropertyDecorator('_setReference', 'reference')
-
-  security.declareProtected(Permissions.ModifyPortalContent, '_setVersion')
-  _setVersion = _recordPropertyDecorator('_setVersion', 'version')
-
-  security.declareProtected(Permissions.ModifyPortalContent, '_setTextContent')
-  _setTextContent = _recordPropertyDecorator('_setTextContent', 'text_content')
-
   def checkConsistencyAndValidate(self):
     """
     When a Component is in validated or modified validation state and
@@ -172,42 +225,10 @@ class ComponentMixin(PropertyRecordableMixin, Base):
       workflow = self.workflow_history['component_validation_workflow'][-1]
       workflow['error_list'] = error_list
     else:
-      self.clearRecordedProperty('reference')
-      self.clearRecordedProperty('version')
-      self.clearRecordedProperty('text_content')
-      self.validate()
-
-  def _getRecordedPropertyDecorator(accessor_name, property_name):
-    def inner(self, validated_only=False):
-      """
-      When validated_only is True, then returns the property recorded if the
-      Component has been modified but there was an error upon consistency
-      checking
-      """
-      if validated_only:
-        try:
-          return self.getRecordedProperty(property_name)
-        # AttributeError when this property has never been recorded before
-        # (_recorded_property_dict) and KeyError if the property has been
-        # recorded before but is not anymore
-        except (AttributeError, KeyError):
-          pass
-
-      return getattr(super(ComponentMixin, self), accessor_name)()
-
-    return inner
-
-  security.declareProtected(Permissions.AccessContentsInformation,
-                            'getReference')
-  getReference = _getRecordedPropertyDecorator('getReference', 'reference')
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getVersion')
-  getVersion = _getRecordedPropertyDecorator('getVersion', 'version')
+      for property_name in _recorded_property_name_tuple:
+        self.clearRecordedProperty(property_name)
 
-  security.declareProtected(Permissions.AccessContentsInformation,
-                            'getTextContent')
-  getTextContent = _getRecordedPropertyDecorator('getTextContent',
-                                                 'text_content')
+      self.validate()
 
   security.declareProtected(Permissions.AccessContentsInformation,
                             'getErrorMessageList')