public SharpAssemblyReturnType(SharpAssembly_ assembly, TypeDef[] typeDefTable, uint index)
 {
     underlyingClass = SharpAssemblyClass.FromTypeDef(assembly, index);
     if (underlyingClass != null) {
         FullyQualifiedName = underlyingClass.FullyQualifiedName;
     } else {
         FullyQualifiedName = assembly.Reader.GetStringFromHeap(typeDefTable[index].NSpace) + "." +
                                                 assembly.Reader.GetStringFromHeap(typeDefTable[index].Name);
     }
     declaredin = assembly;
 }
 public SharpAssemblyReturnType(SharpAssembly_ assembly, TypeRef[] typeRefTable, uint index)
 {
     underlyingClass = SharpAssemblyClass.FromTypeRef(assembly, index);
     if (underlyingClass != null) {
         FullyQualifiedName = underlyingClass.FullyQualifiedName;
     } else {
         FullyQualifiedName = assembly.Reader.GetStringFromHeap(typeRefTable[index].Nspace) + "." +
                                                     assembly.Reader.GetStringFromHeap(typeRefTable[index].Name);
         Runtime.LoggingService.Info("SharpAssemblyReturnType from TypeRef: TypeRef not resolved!");
     }
     declaredin = assembly.GetRefAssemblyFor(index);
 }
        public SharpAssemblyField(SharpAssembly_ assembly, Field[] fieldTable, SharpAssemblyClass declaringtype, uint index)
        {
            if (assembly == null) {
                throw new System.ArgumentNullException("assembly");
            }
            if (fieldTable == null) {
                throw new System.ArgumentNullException("fieldTable");
            }
            if (declaringtype == null) {
                throw new System.ArgumentNullException("declaringtype");
            }
            if (index > fieldTable.GetUpperBound(0) || index < 0) {
                throw new System.ArgumentOutOfRangeException("index", index, String.Format("must be between 1 and {0}!", fieldTable.GetUpperBound(0)));
            }

            declaringType = declaringtype;

            Field field = fieldTable[index];
            string name = assembly.Reader.GetStringFromHeap(field.Name);
            FullyQualifiedName = String.Concat(declaringType.FullyQualifiedName, ".", name);

            // Attributes
            ArrayList attrib = assembly.Attributes.Field[index] as ArrayList;
            if (attrib == null) goto noatt;

            AbstractAttributeSection sect = new AbstractAttributeSection();

            foreach(SharpCustomAttribute customattribute in attrib) {
                sect.Attributes.Add(new SharpAssemblyAttribute(assembly, customattribute));
            }

            attributes.Add(sect);

            noatt:

            if (field.IsFlagSet(Field.FLAG_INITONLY)) {
                modifiers |= ModifierEnum.Readonly;
            }

            if (field.IsFlagSet(Field.FLAG_STATIC)) {
                modifiers |= ModifierEnum.Static;
            }

            if (field.IsMaskedFlagSet(Field.FLAG_PRIVATE, Field.FLAG_FIELDACCESSMASK)) { // I assume that private is used most and public last (at least should be)
                modifiers |= ModifierEnum.Private;
            } else if (field.IsMaskedFlagSet(Field.FLAG_FAMILY, Field.FLAG_FIELDACCESSMASK)) {
                modifiers |= ModifierEnum.Protected;
            } else if (field.IsMaskedFlagSet(Field.FLAG_PUBLIC, Field.FLAG_FIELDACCESSMASK)) {
                modifiers |= ModifierEnum.Public;
            } else if (field.IsMaskedFlagSet(Field.FLAG_ASSEMBLY, Field.FLAG_FIELDACCESSMASK)) {
                modifiers |= ModifierEnum.Internal;
            } else if (field.IsMaskedFlagSet(Field.FLAG_FAMORASSEM, Field.FLAG_FIELDACCESSMASK)) {
                modifiers |= ModifierEnum.ProtectedOrInternal;
            } else if (field.IsMaskedFlagSet(Field.FLAG_FAMANDASSEM, Field.FLAG_FIELDACCESSMASK)) {
                modifiers |= ModifierEnum.Protected;
                modifiers |= ModifierEnum.Internal;
            }

            if (field.IsFlagSet(Field.FLAG_LITERAL)) {
                modifiers |= ModifierEnum.Const;
            }

            if (field.IsFlagSet(Field.FLAG_SPECIALNAME)) {
                modifiers |= ModifierEnum.SpecialName;
            }

            // field return type
            uint sigOffset = field.Signature;
            assembly.Reader.LoadBlob(ref sigOffset);
            sigOffset++;  // skip field id
            returnType = new SharpAssemblyReturnType(assembly, ref sigOffset);

            // field constant value -- for enums
            Constant cst = (Constant)assembly.FieldConstantTable[index];
            if (declaringtype.ClassType == ClassType.Enum && cst != null) {
                try {
                    DataType dt = (DataType)cst.Type;

                    byte[] blob = assembly.Reader.GetBlobFromHeap(cst.Val);
                    BinaryReader binReader = new BinaryReader(new MemoryStream(blob));

                    switch (dt) {
                        case DataType.Byte:
                            initialValue = binReader.ReadByte();
                            break;
                        case DataType.Int16:
                            initialValue = binReader.ReadInt16();
                            break;
                        case DataType.Int32:
                            initialValue = binReader.ReadInt32();
                            break;
                        case DataType.Int64:
                            initialValue = binReader.ReadInt64();
                            break;
                        case DataType.SByte:
                            initialValue = binReader.ReadSByte();
                            break;
                        case DataType.UInt16:
                            initialValue = binReader.ReadUInt16();
                            break;
                        case DataType.UInt32:
                            initialValue = binReader.ReadUInt32();
                            break;
                        case DataType.UInt64:
                            initialValue = binReader.ReadUInt64();
                            break;
                        default: // not supported
                            break;
                    }
                    binReader.Close();
                } catch {
                    Runtime.LoggingService.Info("SharpAssemblyField: Error reading constant value");
                }
            }
        }
        public SharpAssemblyAttribute(SharpAssembly_ assembly, SharpCustomAttribute attribute)
        {
            uint sigOffset = 0;

            if (attribute.IsMemberRef) {
                MemberRef[] memberTable = assembly.Tables.MemberRef;

                sigOffset = memberTable[attribute.MemberIndex].Signature;
                uint trIndex = memberTable[attribute.MemberIndex].Class;

                int table = assembly.Reader.GetCodedIndexTable(CodedIndex.MemberRefParent, ref trIndex);
                if (table != 1) {
                    Runtime.LoggingService.Info("SharpAssemblyAttribute: unsupported MemberRefParent coded index");
                    return; // unsupported
                }

                attributeType = SharpAssemblyClass.FromTypeRef(assembly, trIndex);

            } else {
                TypeDef[] typeDefTable = assembly.Tables.TypeDef;

                sigOffset = assembly.Tables.Method[attribute.MemberIndex].Signature;
                uint tdIndex = 0;

                for (uint i = 1; i <= typeDefTable.GetUpperBound(0); ++i) {
                    if (typeDefTable[i].MethodList <= attribute.MemberIndex && i == typeDefTable.GetUpperBound(0)) {
                        tdIndex = i;
                        break;
                    }
                    if (typeDefTable[i].MethodList <= attribute.MemberIndex && typeDefTable[i+1].MethodList > attribute.MemberIndex) {
                        tdIndex = i;
                        break;
                    }
                }

                attributeType = SharpAssemblyClass.FromTypeDef(assembly, tdIndex);
            }
            if (attributeType != null) name = attributeType.FullyQualifiedName;

            if (attribute.ValueIndex == 0) return;

            try {

                // Get return types of positional arguments by inspecting the method signature
                assembly.Reader.LoadBlob(ref sigOffset);
                sigOffset += 1;  // skip calling convention
                int numReturnTypes = assembly.Reader.LoadBlob(ref sigOffset);

                new SharpAssemblyReturnType(assembly, ref sigOffset);

                SharpAssemblyReturnType[] returnTypes = new SharpAssemblyReturnType[numReturnTypes];
                for (int i = 0; i < returnTypes.Length; ++i) {
                    returnTypes[i] = new SharpAssemblyReturnType(assembly, ref sigOffset);
                }

                // Get the return type values and the named arguments
                byte[] argBlob = assembly.Reader.GetBlobFromHeap(attribute.ValueIndex);
                Stream str = new MemoryStream(argBlob);
                BinaryReader binaryReader = new BinaryReader(str);

                ushort prolog = binaryReader.ReadUInt16();
                if (prolog != 1) {
                    Runtime.LoggingService.Info("SharpAssemblyAttribute: Wrong prolog in argument list");
                    return;
                }

                // read positional arguments
                for (int i = 0; i < returnTypes.Length; ++i) {
                    string rettypename = returnTypes[i].Name;

                    SharpAssemblyClass underlyingClass = returnTypes[i].UnderlyingClass;

                    // enum -> determine base integer size and try to display the user-friendly name of the value
                    if (underlyingClass != null && underlyingClass.IsSubclassOf("System.Enum")) {
                        //underlyingClass.LoadMembers();
                        foreach (IField field in underlyingClass.Fields) {
                            if (field.Name.EndsWith("value__")) {
                                rettypename = field.ReturnType.Name;
                                break;
                            }
                        }

                        Runtime.LoggingService.Info("Enum: return type = " + rettypename);

                        object argValue = GetFixedArg(argBlob, binaryReader, rettypename);

                        Runtime.LoggingService.Info("Enum: arg value = " + argValue.ToString());

                            foreach (IField field in underlyingClass.Fields) {
                                if (field is SharpAssemblyField) {
                                    try {
                                        if (((field as SharpAssemblyField).InitialValue as IComparable).CompareTo(argValue) == 0) {
                                            positionalArguments.Add(underlyingClass.Name + "." + field.Name);
                                            goto namefound;
                                        }
                                    } catch {}
                                }
                            }
                        						// if the value cannot be found
                        positionalArguments.Add(argValue.ToString());

                        Runtime.LoggingService.Info("Enum: no name found");

                    namefound: ;

                    } else {
                        positionalArguments.Add(GetFixedArg(argBlob, binaryReader, rettypename).ToString());
                    }
                }

                ushort numnamed = binaryReader.ReadUInt16();

                for (int i = 0; i < numnamed; ++i) {
                    /*byte field_or_prop = */ binaryReader.ReadByte();
                    byte type = binaryReader.ReadByte();

                    string typename = "";
                    if (type == 0x50) {
                        typename = "Type";
                    } else {
                        DataType dt = (DataType)type;
                        typename = dt.ToString();
                    }

                    string argname = GetSerString(argBlob, binaryReader.BaseStream);

                    namedArguments.Add(argname, GetFixedArg(argBlob, binaryReader, typename).ToString());
                }

                binaryReader.Close();
            } catch (Exception) {
                Runtime.LoggingService.Info("SharpAssemblyAttribute: Error loading arguments.");
                //Runtime.LoggingService.Info(e.ToString());
            }
        }
        public static SharpAssemblyClass[] GetAssemblyTypes(SharpAssembly_ assembly)
        {
            TypeDef[] typeDefTable = assembly.Tables.TypeDef;
            if (typeDefTable == null) return new SharpAssemblyClass[0];

            ArrayList classes = new ArrayList();

            for (uint i = 1; i <= typeDefTable.GetUpperBound(0); ++i) {
                try {
                    IClass newclass = new SharpAssemblyClass(assembly, typeDefTable, i);
                    classes.Add(newclass);
                } catch {
                    Runtime.LoggingService.Info("GetAssemblyTypes: Error loading class " + i);
                }
            }

            return (SharpAssemblyClass[])classes.ToArray(typeof(SharpAssemblyClass));
        }
        public SharpAssemblyMethod(SharpAssembly_ asm, Method[] methodTable, SharpAssemblyClass declaringtype, uint index)
        {
            if (asm == null) {
                throw new System.ArgumentNullException("asm");
            }
            if (methodTable == null) {
                throw new System.ArgumentNullException("methodTable");
            }
            if (declaringtype == null) {
                throw new System.ArgumentNullException("declaringType");
            }
            if (index > methodTable.GetUpperBound(0) || index < 1) {
                throw new System.ArgumentOutOfRangeException("index", index, String.Format("must be between 1 and {0}!", methodTable.GetUpperBound(0)));
            }
            AssemblyReader assembly = asm.Reader;

            declaringType = declaringtype;

            Method methodDef = methodTable[index];
            string name = assembly.GetStringFromHeap(methodDef.Name);

            FullyQualifiedName = String.Concat(declaringType.FullyQualifiedName, ".", name);

            // Attributes
            ArrayList attrib = asm.Attributes.Method[index] as ArrayList;
            if (attrib == null) goto noatt;

            AbstractAttributeSection sect = new AbstractAttributeSection();

            foreach(SharpCustomAttribute customattribute in attrib) {
                sect.Attributes.Add(new SharpAssemblyAttribute(asm, customattribute));
            }

            attributes.Add(sect);

            noatt:

            modifiers = ModifierEnum.None;

            if (methodDef.IsFlagSet(Method.FLAG_STATIC)) {
                modifiers |= ModifierEnum.Static;
            }

            if (methodDef.IsMaskedFlagSet(Method.FLAG_PRIVATE, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.Private;
            } else if (methodDef.IsMaskedFlagSet(Method.FLAG_PUBLIC, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.Public;
            } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMILY, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.Protected;
            } else if (methodDef.IsMaskedFlagSet(Method.FLAG_ASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.Internal;
            } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMORASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.ProtectedOrInternal;
            } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMANDASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                modifiers |= ModifierEnum.Protected;
                modifiers |= ModifierEnum.Internal;
            }

            if (methodDef.IsFlagSet(Method.FLAG_VIRTUAL)) {
                modifiers |= ModifierEnum.Virtual;
            }

            if (methodDef.IsFlagSet(Method.FLAG_FINAL)) {
                modifiers |= ModifierEnum.Final;
            }

            if (methodDef.IsFlagSet(Method.FLAG_ABSTRACT)) {
                modifiers |= ModifierEnum.Abstract;
            }

            if (methodDef.IsFlagSet(Method.FLAG_SPECIALNAME)) {
                modifiers |= ModifierEnum.SpecialName;
            }

            uint offset = methodDef.Signature;
            assembly.LoadBlob(ref offset);
            offset += 1;  // skip calling convention
            int numReturnTypes = assembly.LoadBlob(ref offset);

            returnType = new SharpAssemblyReturnType(asm, ref offset);

            IReturnType[] returnTypes = new IReturnType[numReturnTypes];
            for (int i = 0; i < returnTypes.Length; ++i) {
                returnTypes[i] = new SharpAssemblyReturnType(asm, ref offset);
            }

            AddParameters(asm, methodTable, index, returnTypes);
        }
        public SharpAssemblyProperty(SharpAssembly_ asm, Property[] propertyTable, SharpAssemblyClass declaringtype, uint index)
        {
            if (asm == null) {
                throw new System.ArgumentNullException("asm");
            }
            if (propertyTable == null) {
                throw new System.ArgumentNullException("propertyTable");
            }
            if (declaringtype == null) {
                throw new System.ArgumentNullException("declaringType");
            }
            if (index > propertyTable.GetUpperBound(0) || index < 1) {
                throw new System.ArgumentOutOfRangeException("index", index, String.Format("must be between 1 and {0}!", propertyTable.GetUpperBound(0)));
            }

            AssemblyReader assembly = asm.Reader;
            declaringType = declaringtype;

            Property property = asm.Tables.Property[index];
            string name = assembly.GetStringFromHeap(property.Name);
            FullyQualifiedName = String.Concat(declaringType.FullyQualifiedName, ".", name);

            MethodSemantics[] sem = (MethodSemantics[])assembly.MetadataTable.Tables[MethodSemantics.TABLE_ID];
            Method[] method       = (Method[])assembly.MetadataTable.Tables[Method.TABLE_ID];

            uint getterMethodIndex = 0; // used later for parameters

            if (sem == null) goto nosem;

            for (int i = 1; i <= sem.GetUpperBound(0); ++i) {
                uint table = sem[i].Association & 1;
                uint ident = sem[i].Association >> 1;

                if (table == 1 && ident == index) {  // table: Property
                    modifiers = ModifierEnum.None;
                    Method methodDef = method[sem[i].Method];

                    if (methodDef.IsFlagSet(Method.FLAG_STATIC)) {
                        modifiers |= ModifierEnum.Static;
                    }

                    if (methodDef.IsFlagSet(Method.FLAG_ABSTRACT)) {
                        modifiers |= ModifierEnum.Abstract;
                    }

                    if (methodDef.IsFlagSet(Method.FLAG_VIRTUAL)) {
                        modifiers |= ModifierEnum.Virtual;
                    }

                    if (methodDef.IsFlagSet(Method.FLAG_FINAL)) {
                        modifiers |= ModifierEnum.Final;
                    }

                    if (methodDef.IsMaskedFlagSet(Method.FLAG_PRIVATE, Method.FLAG_MEMBERACCESSMASK)) { // I assume that private is used most and public last (at least should be)
                        modifiers |= ModifierEnum.Private;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMILY, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Protected;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_PUBLIC, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Public;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_ASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Internal;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMORASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.ProtectedOrInternal;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMANDASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Protected;
                        modifiers |= ModifierEnum.Internal;
                    }

                    if ((sem[i].Semantics & MethodSemantics.SEM_GETTER) == MethodSemantics.SEM_GETTER) {
                        getterRegion = new DefaultRegion(0, 0, 0, 0);
                        getterMethod = new SharpAssemblyMethod(asm, method, declaringtype, sem[i].Method);
                        getterMethodIndex = sem[i].Method;
                    }

                    if ((sem[i].Semantics & MethodSemantics.SEM_SETTER) == MethodSemantics.SEM_SETTER) {
                        setterRegion = new DefaultRegion(0, 0, 0, 0);
                        setterMethod = new SharpAssemblyMethod(asm, method, declaringtype, sem[i].Method);
                    }
                }

            }

            nosem:

            // Attributes
            ArrayList attrib = asm.Attributes.Property[index] as ArrayList;
            if (attrib == null) goto noatt;

            AbstractAttributeSection sect = new AbstractAttributeSection();

            foreach(SharpCustomAttribute customattribute in attrib) {
                sect.Attributes.Add(new SharpAssemblyAttribute(asm, customattribute));
            }

            attributes.Add(sect);

            noatt:

            if ((property.Flags & Property.FLAG_SPECIALNAME) == Property.FLAG_SPECIALNAME) modifiers |= ModifierEnum.SpecialName;

            uint offset = property.Type;
            assembly.LoadBlob(ref offset);
            offset += 1; // skip calling convention
            int paramCount = assembly.LoadBlob(ref offset);

            returnType = new SharpAssemblyReturnType(asm, ref offset);

            IReturnType[] returnTypes = new IReturnType[paramCount];
            for (int i = 0; i < returnTypes.Length; ++i) {
                returnTypes[i] = new SharpAssemblyReturnType(asm, ref offset);
            }

            if (getterMethodIndex != 0) {
                AddParameters(asm, asm.Tables.Method, getterMethodIndex, returnTypes);
            } else {
                AddParameters(asm, returnTypes);
            }
        }
        public void GetDataType(SharpAssembly_ asm, ref uint offset)
        {
            AssemblyReader assembly = asm.Reader;
            string fullyQualifiedName = "";
            DataType dt = (DataType)assembly.LoadBlob(ref offset);
            switch (dt) {
                case DataType.Void:
                case DataType.Boolean:
                case DataType.Char:
                case DataType.SByte:
                case DataType.Byte:
                case DataType.Int16:
                case DataType.UInt16:
                case DataType.Int32:
                case DataType.UInt32:
                case DataType.Int64:
                case DataType.UInt64:
                case DataType.Single:
                case DataType.Double:
                case DataType.String:
                case DataType.Object:
                case DataType.IntPtr:
                case DataType.UIntPtr:
                    fullyQualifiedName = "System." + dt.ToString();

                    // TODO : underlyingClass
                    declaredin = asm.GetReference("mscorlib");
                    break;

                case DataType.SZArray:
                    GetDataType(asm, ref offset);
                    arrayRanks.Add(0);
                    break;

                case DataType.Array:
                    GetDataType(asm, ref offset);
                    int rank      = assembly.LoadBlob(ref offset);
                    int num_sizes = assembly.LoadBlob(ref offset);
                    int[] sizes   = new int[num_sizes];
                    for (int i = 0; i < num_sizes; ++i) {
                        sizes[i] = assembly.LoadBlob(ref offset);
                    }
                    int num_lowerBounds = assembly.LoadBlob(ref offset);
                    int[] lowerBounds   = new int[num_lowerBounds];
                    for (int i = 0; i < num_lowerBounds; ++i) {
                        lowerBounds[i] = assembly.LoadBlob(ref offset);
                    }
                    arrayRanks.Add(rank - 1);
                    break;

                case DataType.ValueType:
                case DataType.Class:
                    uint idx = (uint)assembly.LoadBlob(ref offset);
                    bool isTypeRef = (idx & 1) == 1;
                    uint  index    = (idx >> 2);

                    TypeDef[] typeDefTable = asm.Tables.TypeDef;
                    TypeRef[] typeRefTable = asm.Tables.TypeRef;

                    if (isTypeRef) {
                        underlyingClass = SharpAssemblyClass.FromTypeRef(asm, index);
                        if (underlyingClass != null) {
                            fullyQualifiedName = underlyingClass.FullyQualifiedName;
                        } else {
                            fullyQualifiedName = assembly.GetStringFromHeap(typeRefTable[index].Nspace) + "." +
                                                                        assembly.GetStringFromHeap(typeRefTable[index].Name);
                            Runtime.LoggingService.Info("GetDataType: TypeRef not resolved!");
                        }
                        declaredin = asm.GetRefAssemblyFor(index);
                    } else {
                        underlyingClass = SharpAssemblyClass.FromTypeDef(asm, index);
                        if (underlyingClass != null) {
                            fullyQualifiedName = underlyingClass.FullyQualifiedName;
                        } else {
                            fullyQualifiedName = assembly.GetStringFromHeap(typeDefTable[index].NSpace) + "." +
                                                                    assembly.GetStringFromHeap(typeDefTable[index].Name);
                        }
                        declaredin = asm;
                    }

                    break;

                case DataType.Ptr:
                    GetDataType(asm, ref offset);
                    ++pointerNestingLevel;
                    break;
                case DataType.ByRef:
                    GetDataType(asm, ref offset);
                    fullyQualifiedName += "&";
                    break;

                case DataType.TypeReference:
                    fullyQualifiedName = "typedref";
                    break;

                case DataType.Pinned:
                    GetDataType(asm, ref offset);
                    //fullyQualifiedName += " pinned";
                    break;

                case DataType.CModOpt:
                case DataType.CModReq:
                    GetDataType(asm, ref offset);
                    break;

                default:
                    Runtime.LoggingService.Info("NOT supported: " + dt.ToString());
                    fullyQualifiedName += " NOT_SUPPORTED [" + dt.ToString() + "]";
                    break;
            }
            base.FullyQualifiedName = fullyQualifiedName;
        }
        public SharpAssemblyEvent(SharpAssembly_ asm, Event[] eventTable, SharpAssemblyClass declaringtype, uint index)
        {
            if (asm == null) {
                throw new System.ArgumentNullException("asm");
            }
            if (eventTable == null) {
                throw new System.ArgumentNullException("eventTable");
            }
            if (declaringtype == null) {
                throw new System.ArgumentNullException("declaringtype");
            }
            if (index > eventTable.GetUpperBound(0) || index < 1) {
                throw new System.ArgumentOutOfRangeException("index", index, String.Format("must be between 1 and {0}!", eventTable.GetUpperBound(0)));
            }

            AssemblyReader assembly = asm.Reader;

            declaringType = declaringtype;

            Event evt = eventTable[index];
            string name = assembly.GetStringFromHeap(evt.Name);
            FullyQualifiedName = String.Concat(declaringType.FullyQualifiedName, ".", name);

            MethodSemantics[] sem = asm.Tables.MethodSemantics;
            Method[] method       = asm.Tables.Method;
            if (sem == null) goto nosem;

            for (int i = 1; i <= sem.GetUpperBound(0); ++i) {
                uint table = sem[i].Association & 1;
                uint ident = sem[i].Association >> 1;

                if (table == 0 && ident == index) {  // table: Event
                    modifiers = ModifierEnum.None;
                    Method methodDef = method[sem[i].Method];

                    if (methodDef.IsFlagSet(Method.FLAG_STATIC)) {
                        modifiers |= ModifierEnum.Static;
                    }

                    if (methodDef.IsMaskedFlagSet(Method.FLAG_PRIVATE, Method.FLAG_MEMBERACCESSMASK)) { // I assume that private is used most and public last (at least should be)
                        modifiers |= ModifierEnum.Private;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMILY, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Protected;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_PUBLIC, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Public;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_ASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Internal;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMORASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.ProtectedOrInternal;
                    } else if (methodDef.IsMaskedFlagSet(Method.FLAG_FAMANDASSEM, Method.FLAG_MEMBERACCESSMASK)) {
                        modifiers |= ModifierEnum.Protected;
                        modifiers |= ModifierEnum.Internal;
                    }

                    if ((sem[i].Semantics & MethodSemantics.SEM_ADDON) == MethodSemantics.SEM_ADDON) {
                        addMethod = new SharpAssemblyMethod(asm, method, declaringtype, sem[i].Method);
                    }

                    if ((sem[i].Semantics & MethodSemantics.SEM_REMOVEON) == MethodSemantics.SEM_REMOVEON) {
                        removeMethod = new SharpAssemblyMethod(asm, method, declaringtype, sem[i].Method);
                    }

                    if ((sem[i].Semantics & MethodSemantics.SEM_FIRE) == MethodSemantics.SEM_FIRE) {
                        raiseMethod = new SharpAssemblyMethod(asm, method, declaringtype, sem[i].Method);
                    }
                }

            }

            nosem:

            // Attributes
            ArrayList attrib = asm.Attributes.Event[index] as ArrayList;
            if (attrib == null) goto noatt;

            AbstractAttributeSection sect = new AbstractAttributeSection();

            foreach(SharpCustomAttribute customattribute in attrib) {
                sect.Attributes.Add(new SharpAssemblyAttribute(asm, customattribute));
            }

            attributes.Add(sect);

            noatt:

            if ((evt.EventFlags & Event.FLAG_SPECIALNAME) == Event.FLAG_SPECIALNAME) modifiers |= ModifierEnum.SpecialName;

            uint typtab = evt.EventType & 0x03;
            uint typid  = evt.EventType >> 2;

            if (typtab == 0) {        // TypeDef
                TypeDef[] typedef = (TypeDef[])assembly.MetadataTable.Tables[TypeDef.TABLE_ID];
                returnType = new SharpAssemblyReturnType(asm, typedef, typid);

            } else if (typtab == 1) { // TypeRef
                TypeRef[] typeref = (TypeRef[])assembly.MetadataTable.Tables[TypeRef.TABLE_ID];
                returnType = new SharpAssemblyReturnType(asm, typeref, typid);

            } else {                  // TypeSpec
                returnType = new SharpAssemblyReturnType("NOT_SUPPORTED");
                Runtime.LoggingService.Info("SharpAssemblyEvent: TypeSpec -- not supported");
            }
        }