/// <summary> /// Processes the specified type. /// </summary> /// <param name="theType">The type to process.</param> /// <returns>The debug database type info created during processing.</returns> private DB_Type ProcessType(Type theType, bool partialprocess = false) { if (theType.IsValueType || theType.IsPointer) { partialprocess = false; } //TODO - How are we handling interfaces? if (!AllTypes.Contains(theType)) { AllTypes.Add(theType); } if (!ProcessedTypes.Contains(theType)) { if (ProcessingTypes.Count == 0) { //We must start processing of types from the bottom of a type inheritance chain // otherwise we end up in a dependency loop! List<Type> childTypes = (from types in AllTypes where (types.IsSubclassOf(theType)) select types).ToList(); if (childTypes.Count > 0) { for (int i = 0; i < childTypes.Count; i++) { ProcessType(childTypes[i]); } } } if (!ProcessedTypes.Contains(theType)) { try { ProcessingTypes.Add(theType); if (!partialprocess) { ProcessedTypes.Add(theType); } string TypeId = TheScannerState.GetTypeID(theType); DB_Type TheDBType = DebugDatabase.GetType(TypeId); if (TheDBType == null) { TheDBType = new DB_Type(); TheDBType.Id = TypeId; TheDBType.Signature = theType.FullName; TheDBType.StackBytesSize = Utils.GetNumBytesForType(theType); TheDBType.IsValueType = theType.IsValueType; TheDBType.IsPointerType = theType.IsPointer; DebugDatabase.AddType(TheDBType); DebugDatabase.SubmitChanges(); } if (!partialprocess) { int totalMemSize = 0; int index = 0; List<DB_ComplexTypeLink> complexTypeLinks = new List<DB_ComplexTypeLink>(); //Process inherited fields like this so that (start of) the memory structures // of all types that inherit from this base type are the same i.e. inherited // fields appear in at same offset memory for all inheriting types if (theType.BaseType != null) { Type baseType = theType.BaseType; if (!baseType.AssemblyQualifiedName.Contains("mscorlib")) { DB_Type baseDBType = ProcessType(baseType); TheDBType.BaseTypeId = baseDBType.Id; totalMemSize += baseDBType.BytesSize; foreach (DB_ComplexTypeLink childLink in baseDBType.ChildTypes) { DB_ComplexTypeLink DBTypeLink = new DB_ComplexTypeLink(); DBTypeLink.Id = Guid.NewGuid(); DBTypeLink.ParentTypeID = TheDBType.Id; DBTypeLink.ChildTypeID = childLink.ChildTypeID; DBTypeLink.ParentIndex = childLink.ParentIndex; DBTypeLink.FieldId = childLink.FieldId; complexTypeLinks.Add(DBTypeLink); index++; } } } if (!theType.AssemblyQualifiedName.Contains("mscorlib")) { List<FieldInfo> AllFields = theType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList(); foreach (FieldInfo anInfo in AllFields) { //Ignore inherited fields - process inherited fields above if (anInfo.DeclaringType == theType) { DB_Type childDBType = ProcessType(anInfo.FieldType, true); totalMemSize += childDBType.IsValueType ? childDBType.BytesSize : childDBType.StackBytesSize; DB_ComplexTypeLink DBTypeLink = new DB_ComplexTypeLink(); DBTypeLink.Id = Guid.NewGuid(); DBTypeLink.ParentTypeID = TheDBType.Id; DBTypeLink.ChildTypeID = childDBType.Id; DBTypeLink.ParentIndex = index; DBTypeLink.FieldId = anInfo.Name; complexTypeLinks.Add(DBTypeLink); index++; } } } if ((theType.IsValueType && totalMemSize == 0) || theType.IsPointer) { totalMemSize = Utils.GetSizeForType(theType); } TheDBType.BytesSize = totalMemSize; foreach (DB_ComplexTypeLink typeLink in complexTypeLinks) { DebugDatabase.AddComplexTypeLink(typeLink); } DebugDatabase.SubmitChanges(); TheScannerState.AddType(TheDBType); TheScannerState.AddTypeMethods(theType); TheScannerState.AddTypeFields(theType); if (!theType.AssemblyQualifiedName.Contains("mscorlib")) { ProcessStaticFields(theType); } } TypeClassAttribute typeClassAttr = (TypeClassAttribute)theType.GetCustomAttribute(typeof(TypeClassAttribute)); if (typeClassAttr != null) { TheScannerState.TypeClass = theType; } MethodInfoStructAttribute methodInfoStructAttr = (MethodInfoStructAttribute)theType.GetCustomAttribute(typeof(MethodInfoStructAttribute)); if (methodInfoStructAttr != null) { TheScannerState.MethodInfoStruct = theType; } FieldInfoStructAttribute fieldInfoStructAttr = (FieldInfoStructAttribute)theType.GetCustomAttribute(typeof(FieldInfoStructAttribute)); if (fieldInfoStructAttr != null) { TheScannerState.FieldInfoStruct = theType; } ArrayClassAttribute arrayClassAttr = (ArrayClassAttribute)theType.GetCustomAttribute(typeof(ArrayClassAttribute)); if (arrayClassAttr != null) { TheScannerState.ArrayClass = theType; } StringClassAttribute stringClassAttr = (StringClassAttribute)theType.GetCustomAttribute(typeof(StringClassAttribute)); if (stringClassAttr != null) { TheScannerState.StringClass = theType; } return TheDBType; } finally { ProcessingTypes.Remove(theType); } return null; } else { return DebugDatabase.GetType(TheScannerState.GetTypeID(theType)); } } else { return DebugDatabase.GetType(TheScannerState.GetTypeID(theType)); } }
partial void UpdateDB_Type(DB_Type instance);
partial void DeleteDB_Type(DB_Type instance);
private void detach_InheritedTypes(DB_Type entity) { this.SendPropertyChanging(); entity.BaseType = null; }
partial void InsertDB_Type(DB_Type instance);
/// <summary> /// Gets the index of a field in the specified type. /// </summary> /// <param name="dbType">The type to look for the field in.</param> /// <param name="fieldName">The name of the field to look for.</param> /// <returns>Returns the index.</returns> private int GetFieldIndex(DB_Type dbType, string fieldName) { //Get the child links of the type (i.e. the fields of the type) List<DB_ComplexTypeLink> allChildLinks = dbType.ChildTypes.OrderBy(x => x.ParentIndex).ToList(); //Get the DB type information for the field we want to load DB_ComplexTypeLink theTypeLink = (from links in dbType.ChildTypes where links.FieldId == fieldName select links).First(); //Get all the fields that come before the field we want to load //This is so we can calculate the offset (in memory, in bytes) from the start of the object allChildLinks = allChildLinks.Where(x => x.ParentIndex < theTypeLink.ParentIndex).ToList(); //Calculate the offset return allChildLinks.Count(); }
/// <summary> /// Adds the specified type to the Types Table. /// </summary> /// <param name="TheDBType">The type to add.</param> public void AddType(DB_Type TheDBType) { //The structure of an entry in the Types Table must be the same as //the FOS_System.Type class string TypeId = GetTypeIdString(TheDBType.Id); string SizeVal = TheDBType.BytesSize.ToString(); string IdVal = (TypesTable_TotalNumEntries++).ToString(); string StackSizeVal = TheDBType.StackBytesSize.ToString(); string IsValueTypeVal = (TheDBType.IsValueType ? "1" : "0"); string MethodTablePointer = TypeId + "_MethodTable"; string IsPointerTypeVal = (TheDBType.IsPointerType ? "1" : "0"); string BaseTypeIdVal = "0"; if (TheDBType.BaseTypeId != null) { BaseTypeIdVal = GetTypeIdString(TheDBType.BaseTypeId); } string FieldTablePointer = TypeId + "_FieldTable"; string TypeSignatureLiteralLabel = AddStringLiteral(TheDBType.Signature, null); string TypeIdLiteralLabel = AddStringLiteral(TheDBType.Id, null); // We add the info in a presumed order // It is rearranged into the correct order later in Finalise TypesTableDataBlock.ASM.AppendLine(string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}|{10}|{11}", TypeId + ":", TheDBType.Signature, SizeVal, IdVal, StackSizeVal, IsValueTypeVal, MethodTablePointer, IsPointerTypeVal, BaseTypeIdVal, FieldTablePointer, TypeSignatureLiteralLabel, TypeIdLiteralLabel)); }
public int GetFieldOffset(DB_Type dbType, string FieldName) { try { //Get the child links of the type (i.e. the fields of the type) List<DB_ComplexTypeLink> allChildLinks = dbType.ChildTypes.OrderBy(x => x.ParentIndex).ToList(); //Get the DB type information for the field we want to load DB_ComplexTypeLink theTypeLink = (from links in dbType.ChildTypes where links.FieldId == FieldName select links).First(); //Get all the fields that come before the field we want to load //This is so we can calculate the offset (in memory, in bytes) from the start of the object allChildLinks = allChildLinks.Where(x => x.ParentIndex < theTypeLink.ParentIndex).ToList(); //Calculate the offset return allChildLinks.Sum(x => x.ChildType.IsValueType ? x.ChildType.BytesSize : x.ChildType.StackBytesSize); } catch(InvalidOperationException ex) { if (ex.Message.Contains("Sequence contains no elements") && FieldName == "_Type") { throw new Exception("Did you forget to make " + dbType.Signature + " inherit from FOS_System.Object?"); } throw ex; } }
/// <summary> /// Removes the specified type from the database. /// <para>To Do's: See <see cref="RemoveMethod"/>'s to do's.</para> /// </summary> /// <param name="aType">The entry to remove.</param> /// <remarks> /// <para> /// For the moment this method does no more than just directly remove /// the entry from the database. /// </para> /// <para> /// <see cref="SubmitChanges"/> must be called at some point after this /// method for changes to actually be submitted to the database. /// </para> /// </remarks> public static void RemoveType(DB_Type aType) { DB.DB_Types.DeleteOnSubmit(aType); }
/// <summary> /// Adds the pre-created type to the database. All the entries's /// required parameters (i.e. ones which cannot be null) should /// be set. /// <para>To Do's: See <see cref="AddMethod"/>'s to do's.</para> /// </summary> /// <param name="aType">The entry to add.</param> /// <remarks> /// <para> /// For the moment this method does no more than just directly add /// the entry to the database. /// </para> /// <para> /// <see cref="SubmitChanges"/> must be called at some point after this /// method for changes to actually be submitted to the database. /// </para> /// </remarks> public static void AddType(DB_Type aType) { DB.DB_Types.InsertOnSubmit(aType); }