private static Object ExtractArrayValue(Signature.Type type,
                                                BinaryReader reader,
                                                MetaDataResolver resolver,
                                                MetaDataResolver[] resolvers)
        {
            int arraySize = reader.ReadInt32();

            if (arraySize >= 0)
            {
                ElementTypes elementType = type.ElementType;
                if (elementType == ElementTypes.CLASS)
                {
                    Object[] array = new Object[arraySize];
                    for (int i = 0; i < arraySize; i++)
                    {
                        array[i] = ExtractParameter(type, reader,
                                                    resolver, resolvers);
                    }
                    return(array);
                }
                else
                {
                    return(ExtractArrayValue(elementType, arraySize, reader));
                }
            }
            else
            {
                throw new Exception("Not implemented: custom attribute class " +
                                    "array with negative length");
            }
        }
        private static MetaDataTypeDefinition ResolveName(MetaDataResolver resolver,
                                                          MetaDataResolver[] resolvers,
                                                          String typeName)
        {
            MetaDataTypeDefinition typeDef = resolver.ResolveName(typeName);
            int i = 0;

            while (typeDef == null && i < resolvers.Length)
            {
                MetaDataResolver testResolver = resolvers[i];
                i++;
                if (testResolver != resolver)
                {
                    typeDef = testResolver.ResolveName(typeName);
                }
            }
            return(typeDef);
        }
        private static MetaDataObject ResolveTypeRef(MetaDataResolver resolver,
                                                     MetaDataResolver[] resolvers,
                                                     MetaDataTypeReference typeRef)
        {
            MetaDataObject result = resolver.ResolveTypeRef(typeRef);
            int            i      = 0;

            while (result == null && i < resolvers.Length)
            {
                MetaDataResolver testResolver = resolvers[i];
                i++;
                if (testResolver != resolver)
                {
                    result = testResolver.ResolveTypeRef(typeRef);
                }
            }
            return(result);
        }
 private static Object ExtractEnumValue(MetaDataTypeDefinition typeDef,
                                        BinaryReader reader,
                                        MetaDataResolver resolver,
                                        MetaDataResolver[] resolvers)
 {
     MetaDataField[] classFields = typeDef.Fields;
     for (int i = 0; i < classFields.Length; i++)
     {
         if ((classFields[i].Flags & (int)MetaDataField.FieldAttributes.Static) == 0)
         {
             if (!classFields[i].Name.Equals("value__"))
             {
                 throw new MetaDataLoader.IllegalMetaDataFormatException("Found enum with non-static field " + classFields[i].Name);
             }
             return(ExtractParameter(classFields[i].Signature.FieldType,
                                     reader, resolver, resolvers));
         }
     }
     throw new MetaDataLoader.IllegalMetaDataFormatException("Found enum without non-static field");
 }
        // Resolve all the custom attributes found in the assemblies registered
        // in 'resolver', using all the type information found in 'resolver' and
        // 'resolvers'.
        internal void resolveReferences(MetaDataResolver resolver,
                                        MetaDataResolver[] resolvers)
        {
            if (this.buffer[0] != 0x01 || this.buffer[1] != 0x00)
            {
                throw new MetaDataLoader.IllegalMetaDataFormatException("Custom Attribute doesn't start with 0x0001!");
            }
            SignatureMethod signature;

            if (this.type is MetaDataMethod)
            {
                MetaDataMethod method = (MetaDataMethod)this.type;
                signature = (SignatureMethod)method.Signature;
                if (!method.Name.Equals(".ctor"))
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected method name: " + method.Name);
                }
                this.typeDefOrRef = method.Parent;
                this.name         = method.Parent.FullName;
            }
            else if (this.type is MetaDataMemberRef)
            {
                MetaDataMemberRef memberRef = (MetaDataMemberRef)this.type;
                signature = (SignatureMethod)memberRef.Signature;
                if (!memberRef.Name.Equals(".ctor"))
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected memberRef name: " + memberRef.Name);
                }
                MetaDataObject methodParent = memberRef.Class;
                this.typeDefOrRef = methodParent;
                if (methodParent is MetaDataTypeDefinition)
                {
                    this.name = ((MetaDataTypeDefinition)methodParent).FullName;
                }
                else if (methodParent is MetaDataTypeReference)
                {
                    this.name = ((MetaDataTypeReference)methodParent).FullName;
                }
                else
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected class type: " + methodParent);
                }
            }
            else
            {
                throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected type: " + this.type);
            }
            Signature.Param[] parameters = signature.Parameters;
            int fixedCount = parameters.Length;

            this.fixedArgs = new Object[fixedCount];
            MemoryStream stream =
                new MemoryStream(this.buffer, 2, this.buffer.Length - 2, false);
            BinaryReader reader = new BinaryReader(stream);

            for (int i = 0; i < fixedCount; i++)
            {
                Signature.Param parameter = parameters[i];
                Signature.Type  paramType = parameter.Type;
                Object          value     =
                    ExtractParameter(paramType, reader, resolver, resolvers);
                fixedArgs[i] = value;
            }
            short namedCount = ((reader.PeekChar() == -1) ?
                                (short)0 :
                                reader.ReadInt16());

            if (namedCount > this.buffer.Length &&
                this.Name.Equals("System.Runtime.CompilerServices.RequiredAttributeAttribute"))
            {
                // Some CLR libraries have been compiled against a version of
                // mscorlib that had a fixed parameter to RequiredAttribute.
                // Simply ignore whatever the parameter was!
                namedCount = 0;
            }
            this.namedArgs = new NamedArg[namedCount];
            for (int i = 0; i < namedCount; i++)
            {
                SerializationTypes propOrField = (SerializationTypes)
                                                 reader.ReadByte();
                ElementTypes fieldType = (ElementTypes)reader.ReadByte();
                ElementTypes arrayType = ElementTypes.END;
                switch (fieldType)
                {
                case ElementTypes.SZARRAY: {
                    arrayType = (ElementTypes)reader.ReadByte();
                    if (arrayType == (ElementTypes)SerializationTypes.ENUM)
                    {
                        throw new Exception("Not implemented: Array of ENUM " +
                                            "for named field/property");
                    }
                    break;
                }

                case (ElementTypes)SerializationTypes.ENUM: {
                    String enumName = ExtractString(reader);
                    if (enumName.Length == 0)
                    {
                        throw new Exception("Empty enum name");
                    }
                    // Hope it is a 4-byte enum
                    fieldType = (ElementTypes)SerializationTypes.U4;
                    break;
                }

                case (ElementTypes)SerializationTypes.TAGGED_OBJECT: {
                    throw new Exception("Not implemented: " + fieldType +
                                        " for named field/property");
                }

                default: {
                    break;
                }
                }
                String name = ExtractString(reader);
                Object value;
                if (fieldType == ElementTypes.SZARRAY)
                {
                    value = ExtractArrayValue(arrayType, reader);
                }
                else
                {
                    value = ExtractValue(fieldType, reader);
                }
                if (propOrField == SerializationTypes.FIELD ||
                    propOrField == SerializationTypes.PROPERTY)
                {
                    this.namedArgs[i] =
                        new NamedArg(propOrField == SerializationTypes.FIELD,
                                     -1, name, value);
                }
                else
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Unknown prop-or-field type: " + propOrField);
                }
            }
        }
        private static Object ExtractParameter(Signature.Type type,
                                               BinaryReader reader,
                                               MetaDataResolver resolver,
                                               MetaDataResolver[] resolvers)
        {
            switch (type.ElementType)
            {
            case ElementTypes.VALUETYPE: {
                MetaDataObject classObject = type.ClassObject;
                if (classObject is MetaDataTypeReference)
                {
                    MetaDataTypeReference classReference =
                        (MetaDataTypeReference)classObject;
                    MetaDataObject resolvedObject =
                        ResolveTypeRef(resolver, resolvers, classReference);
                    if (resolvedObject is MetaDataTypeDefinition)
                    {
                        classObject = resolvedObject;
                    }
                }
                if (classObject is MetaDataTypeReference)
                {
                    // We will simply assume it is an I4 enum
                    Console.Out.WriteLine("====>>> WARNING: Making I4 enum assumption for " + classObject);
                    return(reader.ReadInt32());
                }
                else if (classObject is MetaDataTypeDefinition)
                {
                    MetaDataTypeDefinition classDef =
                        (MetaDataTypeDefinition)classObject;
                    MetaDataObject superClass = classDef.Extends;
                    String         superName;
                    if (superClass is MetaDataTypeDefinition)
                    {
                        superName =
                            ((MetaDataTypeDefinition)superClass).FullName;
                    }
                    else if (superClass is MetaDataTypeReference)
                    {
                        superName =
                            ((MetaDataTypeReference)superClass).FullName;
                    }
                    else
                    {
                        throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected superclass of valuetype: " + superClass);
                    }
                    if (!superName.Equals("System.Enum"))
                    {
                        throw new MetaDataLoader.IllegalMetaDataFormatException("Found valuetype that wasn't an Enum");
                    }
                    return(ExtractEnumValue(classDef, reader,
                                            resolver, resolvers));
                }
                else
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected valuetype class: " + classObject);
                }
            }

            case ElementTypes.CLASS: {
                MetaDataObject classObject = type.ClassObject;
                if (classObject is MetaDataTypeReference)
                {
                    MetaDataTypeReference classReference =
                        (MetaDataTypeReference)classObject;
                    MetaDataObject resolvedObject =
                        ResolveTypeRef(resolver, resolvers, classReference);
                    if (resolvedObject is MetaDataTypeDefinition)
                    {
                        classObject = resolvedObject;
                    }
                }
                String className;
                if (classObject is MetaDataTypeReference)
                {
                    className =
                        ((MetaDataTypeReference)classObject).FullName;
                }
                else if (classObject is MetaDataTypeDefinition)
                {
                    className =
                        ((MetaDataTypeDefinition)classObject).FullName;
                }
                else
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected class: " + classObject);
                }
                if (className.Equals("System.String"))
                {
                    return(ExtractString(reader));
                }
                else if (className.Equals("System.Object"))
                {
                    goto case ElementTypes.OBJECT;
                }
                else if (className.Equals("System.Type"))
                {
                    return(ExtractString(reader));
                }
                if (!(classObject is MetaDataTypeDefinition))
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Cannot determine whether the following is an array: " + classObject);
                }
                MetaDataObject superClass =
                    ((MetaDataTypeDefinition)classObject).Extends;
                Console.WriteLine("class is " + classObject);
                throw new Exception("Not implemented: object encoding an array");
            }

            case ElementTypes.OBJECT:
            case (ElementTypes)SerializationTypes.TAGGED_OBJECT: {
                SerializationTypes objectType = (SerializationTypes)
                                                reader.ReadByte();
                switch (objectType)
                {
                case SerializationTypes.ENUM: {
                    String typeName = ExtractString(reader);
                    // Some Stringified type names include a bunch of
                    // information past the type, none of which we
                    // are concerned about for the moment.
                    int nameEnd = typeName.IndexOf(',');
                    if (nameEnd >= 0)
                    {
                        typeName = typeName.Substring(0, nameEnd);
                    }
                    // A type defined within another type has a "+"
                    // as the separator.  Convert it to ".", which is
                    // the convention the rest of the reader uses.
                    typeName = typeName.Replace('+', '.');
                    MetaDataTypeDefinition typeDef =
                        ResolveName(resolver, resolvers, typeName);
                    if (typeDef == null)
                    {
                        throw new Exception("No typedef for " + typeName);
                    }
                    return(ExtractEnumValue(typeDef, reader,
                                            resolver, resolvers));
                }

                case SerializationTypes.TYPE: {
                    return(ExtractValue((ElementTypes)objectType,
                                        reader));
                }

                default: {
                    throw new Exception("Found OBJECT type with type " + objectType);
                }
                }
            }

            case ElementTypes.SZARRAY: {
                return(ExtractArrayValue(type.TypeObject, reader,
                                         resolver, resolvers));
            }

            default: {
                return(ExtractValue(type.ElementType, reader));
            }
            }
        }