private static bool ExtractStruct(Pair p, ClrInstanceField field, ClrValueClass structClass, out object result) { result = null; Type type; if (!GetType(p, field.Type, out type)) { return(false); } var fieldInfos = GetFields(type); result = FormatterServices.GetUninitializedObject(type); foreach (var fld in structClass.Type.Fields) { object value = null; if (fld.Type.IsString) { value = structClass.GetStringField(fld.Name); } else if (fld.Type.IsPrimitive) { value = fld.GetValue(structClass.Address, true); } else if (fld.Type.IsValueClass) { if (!ExtractStruct(p, fld, structClass.GetValueClassField(fld.Name), out value)) { continue; } } else if (fld.Type.IsArray) { Array arr = null; if (!ExtractArray(p, structClass.GetObjectField(fld.Name), fld, out arr)) { continue; } value = arr; } else { if (!ExtractRefObject(p, field, structClass.GetObjectField(fld.Name), out value)) { continue; } } fieldInfos[fld.Name].SetValue(result, value); } return(true); }
/// <summary> /// Gets a string field from the object. Note that the type must match exactly, as this method /// will not do type coercion. This method will throw an ArgumentException if no field matches /// the given name. It will throw a NullReferenceException if the target object is null (that is, /// if (IsNull returns true). It will throw an InvalidOperationException if the field is not /// of the correct type. Lastly, it will throw a MemoryReadException if there was an error reading /// the value of this field out of the data target. /// </summary> /// <param name="fieldName">The name of the field to get the value for.</param> /// <returns>The value of the given field.</returns> /// <inheritdoc /> public string GetStringField(string fieldName) => ValueClass.GetStringField(fieldName);