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);