protected MdaField CreateMdaFieldImpl(MdaClassImpl parent, string propName, PropMethodsDescriptor desc, int fieldIndex)
        {
            MdaField resElt;
            PropertiesNode fieldTags = new DefaultPropertiesNode();

            if (desc is ValuePropMethodsDescriptor) {
                ValuePropMethodsDescriptor d = (ValuePropMethodsDescriptor)desc;
                resElt = new MdaValueFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is RefByIdPropMethodsDescriptor) {
                RefByIdPropMethodsDescriptor d = (RefByIdPropMethodsDescriptor)desc;
                resElt = new MdaRefByIdFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is AggrObjRefPropMethodsDescriptor) {
                AggrObjRefPropMethodsDescriptor d = (AggrObjRefPropMethodsDescriptor)desc;
                resElt = new MdaAggrObjRefFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is ListPropMethodsDescriptor) {
                ListPropMethodsDescriptor d = (ListPropMethodsDescriptor)desc;
                resElt = new MdaListFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is SetPropMethodsDescriptor) {
                SetPropMethodsDescriptor d = (SetPropMethodsDescriptor)desc;
                resElt = new MdaSetFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is MapPropMethodsDescriptor) {
                MapPropMethodsDescriptor d = (MapPropMethodsDescriptor)desc;
                resElt = new MdaMapFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else if (desc is ArrayPropMethodsDescriptor) {
                ArrayPropMethodsDescriptor d = (ArrayPropMethodsDescriptor)desc;
                resElt = new MdaArrayFieldImpl (parent, fieldIndex, propName, fieldTags, d);
            }
            else {
                throw new System.InvalidOperationException ("SHOULD NOT OCCUR: unrecognized PropMethodsDescriptor type");
            }
            return resElt;
        }
        // internal
        // ------------------------------------------------------------------------
        protected virtual MdaClass DoLoadMdaType(System.Type typ)
        {
            MdaClassImpl res;
            PropertiesNode classTags = new DefaultPropertiesNode();
            res = new MdaClassImpl(typ, classTags);

            MdaIntropsector introspector = new MdaIntropsector(typ, methodsRecognizers);
            IList<MdaField> fields = new List<MdaField>();
            IList<MdaMethod> methods = new List<MdaMethod>();

            // add MdaFields from PropMethodsDescriptor found by Introspector
            foreach (KeyValuePair<string, PropMethodsDescriptor> entry in introspector.PropMethodsDescriptors)
            {
                string propName = entry.Key;
                PropMethodsDescriptor desc = entry.Value;
                int fieldIndex = fields.Count;
                MdaField resElt = CreateMdaFieldImpl (res, propName, desc, fieldIndex);
                fields.Add(resElt);
            }

            // add MdaMethod from Method found by Introspector
            foreach (System.Reflection.MethodInfo elt in introspector.UnrecognizedMethods)
            {
                int methodIndex = methods.Count;
                PropertiesNode methodTags = new DefaultPropertiesNode();
                MdaMethodImpl resElt = new MdaMethodImpl(res, methodIndex, elt, methodTags);
                System.Reflection.ParameterInfo[] paramInfos = elt.GetParameters();
                MdaMethodParamImpl[] parameters = new MdaMethodParamImpl[paramInfos.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    string paramName = paramInfos[i].Name;
                    PropertiesNode paramTags = new DefaultPropertiesNode();
                    parameters[i] = new MdaMethodParamImpl(resElt, i, paramName,
                                                           paramTags, paramInfos[i].GetType());
                }
                resElt.__initialize_params(parameters);
                methods.Add(resElt);
            }

            // add child MdaField + MdaMethod to their parent MdaClass
            res.__initialize(fields, methods);
            // add Aspect enhancer for MdaClass (+ MdaField / MdaMethod)
            foreach (MdaAspectEnhancer enhancer in aspectEnhancers)
            {
                try
                {
                    enhancer.addClassAspect(res);
                    // also handle all MdaField + MdaMethod (this code may be repeated in each enhancer instead?)
                    foreach (MdaField field in fields)
                    {
                        enhancer.addFieldAspect(field);
                    }
                    foreach (MdaMethod meth in methods)
                    {
                        enhancer.addMethodAspect(meth);
                    }
                }
                catch (System.Exception)
                {
                    string msg = "failed to apply MdaAspectEnhancer '" + enhancer + "' to loaded class: '" + res + "'";
                    log.error(msg);
                    throw new System.Exception(msg);
                }
            }
            return res;
        }