UnityHeapEx.HeapDump.ReportField C# (CSharp) Méthode

ReportField() private méthode

Dumps info on the field in xml. Provides some rough estimate on size taken by its contents, and recursively enumerates fields if this one contains an object reference.
private ReportField ( object root, string depth, FieldInfo fieldInfo ) : int
root object
depth string
fieldInfo System.Reflection.FieldInfo
Résultat int
        private int ReportField(object root, string depth, FieldInfo fieldInfo)
        {
            var v = fieldInfo.GetValue( root );
            int res = 0;
            var ftype = v==null?null:v.GetType();

            writer.WriteLine( depth + "<field type=\"{0}\" name=\"{1}\" runtimetype=\"{2}\">",
                SecurityElement.Escape( fieldInfo.FieldType.GetFormattedName() ),
                SecurityElement.Escape( fieldInfo.Name ),
                SecurityElement.Escape( v==null?"-null-":ftype.GetFormattedName())
                );

            if(v==null)
            {
                res += IntPtr.Size;
            }
            else if( ftype.IsArray )
            {
                // arrays have special treatment b/c we have to work on every array element
                // just like a single value.
                // TODO refactor this so that arry item and non-array field value share code
                var val = v as Array;
                res += IntPtr.Size; // reference size
                if( val != null && !seenObjects.Contains( val ))
                {
                    seenObjects.Add( val );
                    var length = GetTotalLength( val );
                    writer.WriteLine( depth + "  <array length=\"{0}\"/>", length );
                    var eltype = ftype.GetElementType();
                    if( eltype.IsValueType )
                    {
                        if( eltype.IsEnum )
                            eltype = Enum.GetUnderlyingType( eltype );
                        try
                        {
                            res += Marshal.SizeOf( eltype ) * length;
                        }
                        catch( Exception )
                        {
                            writer.WriteLine( depth + "  <error msg=\"Marshal.SizeOf() failed\"/>" );
                        }
                    }
                    else if( eltype == typeof( string ) )
                    {
                        // special case
                        res += IntPtr.Size * length; // array itself

                        foreach( string item in val )
                        {
                            if( item != null )
                            {
                                writer.WriteLine( depth + "  <string length=\"{0}\"/>", item.Length );
                                if(!seenObjects.Contains( val ))
                                {
                                    seenObjects.Add( val );
                                    res += sizeof( char ) * item.Length + sizeof( int );
                                }
                            }
                        }
                    }

                    else
                    {
                        res += IntPtr.Size * length; // array itself
                        foreach( var item in val )
                        {
                            if( item != null )
                            {
                                writer.WriteLine( depth + "  <item type=\"{0}\">", SecurityElement.Escape( item.GetType().GetFormattedName() ) );
                                res += GatherFromRootRecursively( item, depth + "    " );
                                writer.WriteLine( depth + "  </item>");
                            }
                        }
                    }
                }
                else
                {
                    writer.WriteLine( depth + "  <null/>" );
                }
            }
            else if( ftype.IsValueType )
            {
                if( ftype.IsPrimitive )
                {
                    var val = fieldInfo.GetValue( root );
                    res += Marshal.SizeOf( ftype );
                    writer.WriteLine( depth + "  <value value=\"{0}\"/>", val );
                }
                else if( ftype.IsEnum )
                {
                    var val = fieldInfo.GetValue( root );
                    res += Marshal.SizeOf( Enum.GetUnderlyingType( ftype ) );
                    writer.WriteLine( depth + "  <value value=\"{0}\"/>", val );
                }
                else
                {
                    // this is a struct. This code assumes that all structs contain only primitive types,
                    // which is very strong. Structs that contain references will break, and fail to traverse these
                    // references properly
                    int s = 0;
                    try
                    {
                        s = Marshal.SizeOf( ftype );
                    }
                    catch( Exception )
                    {
                        // this breaks if struct has a reference member. We should probably never have such structs, but we'll see...
                        writer.WriteLine( depth + "  <error msg=\"Marshal.SizeOf() failed\"/>" );
                    }
                    writer.WriteLine( depth + "  <struct size=\"{0}\"/>", s );
                    res += s;
                }
            }
            else if( ftype == typeof( string ) )
            {
                // special case
                res += IntPtr.Size; // reference size
                var val = fieldInfo.GetValue( root ) as string;
                if( val != null )
                {
                    writer.WriteLine( depth + "  <string length=\"{0}\"/>", val.Length );
                    if(!seenObjects.Contains( val ))
                    {
                        seenObjects.Add( val );
                        res += sizeof( char ) * val.Length + sizeof( int );
                    }
                }
                else
                    writer.WriteLine( depth + "  <null/>" );
            }
            else
            {
                // this is a reference
                var classVal = fieldInfo.GetValue( root );
                res += IntPtr.Size; // reference size
                if( classVal != null )
                {
                    res += GatherFromRootRecursively( classVal, depth + "  " );
                }
                else
                {
                    writer.WriteLine( depth + "  <null/>" );
                }
            }
            writer.WriteLine( depth + "  <total size=\"{0}\"/>", res );
            writer.WriteLine( depth + "</field>" );

            return res;
        }