// Get the immediate interfaces on this type. public TypeInfo[] GetInterfaces() { List <TypeInfo> interfaces = new List <TypeInfo>(); if (HasReflectionType) { foreach (Type interfaceType in _reflectionType.GetInterfaces()) { interfaces.Add(new TypeInfo(interfaceType)); } } else if (HasTypeRef) { TypeInfo defInfo = TypeRefToTypeDef(_mdToken, true); return(defInfo.GetInterfaces()); } else { System.Diagnostics.Contracts.Contract.Assert(_mdToken.Table == MDTables.Tables.TypeDef); PEFileReader peFile = _assembly.PEFileReader; MDTables mdScope = peFile.MetaData; // Walk through all rows of the interface implementation table, // looking for this _mdToken. uint numRows = mdScope.RowsInTable(MDTables.Tables.InterfaceImpl); for (uint i = 0; i < numRows; i++) { try { mdScope.SeekToRowOfTable(MDTables.Tables.InterfaceImpl, i); uint typeDefRow = mdScope.ReadRowIndex(MDTables.Tables.TypeDef); if (typeDefRow == _mdToken.Index) { MetadataToken interfaceToken = mdScope.ReadMetadataToken(MDTables.Encodings.TypeDefOrRef); interfaces.Add(TypeInfoFromTypeDefOrRef(interfaceToken)); } } catch (GenericsNotImplementedException) // ignore interfaces such as IComparable<int> that aren't relevant to the addin model {} } } return(interfaces.ToArray()); }
// Does a given typedef in the specified PE file implement the specified interface? private bool ImplementsHelper(PEFileReader peFile, MetadataToken typeDefToken, TypeInfo ifaceType) { System.Diagnostics.Contracts.Contract.Requires(typeDefToken.Table == MDTables.Tables.TypeDef); MDTables mdScope = peFile.MetaData; // Walk through all rules of the interface implementation table, // looking for this typeDefToken. If we find it, check to see if // that row says this type implements the specified interface. // If not, continue walking the interface impl table. uint numRows = mdScope.RowsInTable(MDTables.Tables.InterfaceImpl); for (uint i = 0; i < numRows; i++) { mdScope.SeekToRowOfTable(MDTables.Tables.InterfaceImpl, i); uint typeDefRow = mdScope.ReadRowIndex(MDTables.Tables.TypeDef); if (typeDefRow == typeDefToken.Index) { // if we implement it, return true. Else continue. MetadataToken interfaceToken = mdScope.ReadMetadataToken(MDTables.Encodings.TypeDefOrRef); if (ifaceType.HasName) { mdScope.SeekToMDToken(interfaceToken); // Interface for IContract should be a typeref. switch (interfaceToken.Table) { case MDTables.Tables.TypeRef: { MetadataToken resolutionScope = mdScope.ReadMetadataToken(MDTables.Encodings.ResolutionScope); String ifaceName = mdScope.ReadString(); if (!String.Equals(ifaceName, ifaceType._typeName)) { continue; } String ifaceNameSpace = mdScope.ReadString(); if (!String.Equals(ifaceNameSpace, ifaceType._nameSpace)) { continue; } if (MiniAssembly.Equals(ifaceType.Assembly, peFile, resolutionScope)) { return(true); } break; } case MDTables.Tables.TypeDef: { // This type implements an interface defined in the same assembly. // This isn't really interesting for the add-in model, based on what // we've currently designed and our limited use of this class. mdScope.B.ReadUInt32(); // TypeAttributes String ifaceName = mdScope.ReadString(); if (!String.Equals(ifaceName, ifaceType._typeName)) { continue; } String ifaceNameSpace = mdScope.ReadString(); if (!String.Equals(ifaceNameSpace, ifaceType._nameSpace)) { continue; } if (this._assembly.Equals(ifaceType._assembly)) { return(true); } break; } case MDTables.Tables.TypeSpec: // Since we're only looking for IContract, which is non-generic, // we should ignore this row and move on. System.Diagnostics.Contracts.Contract.Assert(false, "Checking whether a type implements a TypeSpec is NYI (generic interface?)"); break; default: System.Diagnostics.Contracts.Contract.Assert(false, "Support for this interface type is NYI"); throw new NotImplementedException(String.Format(CultureInfo.CurrentCulture, Res.UnsupportedInterfaceType, interfaceToken.Table)); } } else { throw new NotImplementedException(); } } } return(false); }
public MiniConstructorInfo[] GetConstructors(bool includePrivate) { System.Diagnostics.Contracts.Contract.Assert(HasToken /* || HasReflectionType*/, "GetConstructors needs a token (or you should uncomment the support for Reflection types)"); List <MiniConstructorInfo> ctors = new List <MiniConstructorInfo>(); /* * if (HasReflectionType) { * System.Reflection.BindingFlags visibility = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public; * if (includePrivate) * visibility |= System.Reflection.BindingFlags.NonPublic; * foreach (System.Reflection.ConstructorInfo ctor in _reflectionType.GetConstructors(visibility)) * ctors.Add(new MiniConstructorInfo(ctor)); * return ctors.ToArray(); * } */ System.Diagnostics.Contracts.Contract.Assert(_mdToken.Table == MDTables.Tables.TypeDef); PEFileReader peFile = _assembly.PEFileReader; peFile.InitMetaData(); MDTables MetaData = peFile.MetaData; MetaData.SeekToMDToken(_mdToken); System.Reflection.TypeAttributes flags = (System.Reflection.TypeAttributes)peFile.B.ReadUInt32(); System.Reflection.TypeAttributes vis = System.Reflection.TypeAttributes.VisibilityMask & flags; bool isPublic = (vis == System.Reflection.TypeAttributes.Public); // don't support NestedPublic if (!includePrivate && !isPublic) { return(new MiniConstructorInfo[0]); } MetaData.ReadStringIndex(); // typename MetaData.ReadStringIndex(); // namespace MetadataToken baseClass = MetaData.ReadMetadataToken(MDTables.Encodings.TypeDefOrRef); // Base class uint firstMemberIndex = MetaData.ReadRowIndex(MDTables.Tables.FieldDef); // Field list uint firstMethodIndex = MetaData.ReadRowIndex(MDTables.Tables.MethodDef); // Method list uint lastMethodIndex; // If this is the last entry in the TypeDef table, then all the rest of the methods in the MethodDef // table belong to this type. Otherwise, look for the methods belonging to the next type. if (_mdToken.Index == MetaData.RowsInTable(MDTables.Tables.TypeDef)) { lastMethodIndex = MetaData.RowsInTable(MDTables.Tables.MethodDef); } else { MetaData.SeekToRowOfTable(MDTables.Tables.TypeDef, _mdToken.Index); // Seek to next type (not off by 1!) peFile.B.ReadUInt32(); // Flags MetaData.ReadStringIndex(); // type name MetaData.ReadStringIndex(); // namespace MetaData.ReadMetadataToken(MDTables.Encodings.TypeDefOrRef); // Next type's base class MetaData.ReadRowIndex(MDTables.Tables.FieldDef); // field list; uint firstMethodOfNextType = MetaData.ReadRowIndex(MDTables.Tables.MethodDef); // method list lastMethodIndex = firstMethodOfNextType - 1; } // Now walk through list of methods, looking for ones w/ the name ".ctor". for (uint i = firstMethodIndex; i <= lastMethodIndex; i++) { MetadataToken method = new MetadataToken(MDTables.Tables.MethodDef, i); MetaData.SeekToMDToken(method); UInt32 rva = peFile.B.ReadUInt32(); UInt16 implFlags = peFile.B.ReadUInt16(); // MethodImplAttributes System.Reflection.MethodAttributes attrs = (System.Reflection.MethodAttributes)peFile.B.ReadUInt16(); // Flags - MethodAttributes // Visibility check if (!includePrivate && (attrs & System.Reflection.MethodAttributes.Public) == 0) { continue; } String methodName = MetaData.ReadString(); // Name // @ if (!String.Equals(methodName, ".ctor")) { continue; } byte[] sig = MetaData.ReadBlob(); try { MiniParameterInfo[] parameters = ParseSig(sig); ctors.Add(new MiniConstructorInfo(parameters)); } catch (GenericsNotImplementedException) { // may be caused by a Generic contract. The user will be warned elsewhere that generic contracts are not supported. /* * if (Warnings != null) { * lock (Warnings) { * Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.UnparsibleConstructorSignature, this.Name, e.GetType().Name, e.Message)); * } * } */ } } // for each .ctor return(ctors.ToArray()); }