Autor Beitrag
Flitzs
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Do 19.06.08 23:41 
Hey,
vielleicht kennt Jemand von euch das Tool/Snippet ObjectDumper, da ich den Source von dem nirgends finden konnte, hab ich ihn versucht nachzuprogrammieren.
Da mehrer Leute sicher mehr Bugs finden als Einer, und da ich mir sicher bin das man da noch was verbessern kann, wäre ich dankbar wenn ihr euch das mal anseht.
Ja der Sinn für die dies nicht kennen, ein Objekt mit sämtlichen Members die interresant sind, über reflection, als String zurückgeben.

{} = IEnumerable
[] = Struct

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
using System;
using System.Reflection;
using System.Collections;

namespace ODS
{
    class Program
    {
        static void Main(string[] args)
        {
         //Aufruf: ObjectDumper.Dump(ObjectToDump)
        }
    }
    public static class ObjectDumper
    {
        /// <summary>
        /// Gibt das Objekt als String zurück
        /// </summary>
        /// <param name="o">Das Objekt</param>
        /// <returns></returns>
        public static string Dump(object o)
        {
            string RetVal = "";
            if (o == nullreturn "";

            try //Nicht gerade optimal aber mit fällt nichts besseres ein, da es abundzu Fehler gibt die ich sonst nicht abfangen kann.
            {

                if (o is IEnumerable && !(o is ValueType) && !(o is string))
                {
                    //IEnumerable
                    RetVal += "{";
                    foreach (object Item in (IEnumerable)o)
                    {
                        RetVal += Dump(Item);

                        if (Item is string)
                        {
                            RetVal = RetVal.Remove(RetVal.Length - 2);
                            RetVal += ", ";
                        }
                    }
                    if (RetVal.Length > 1)
                        RetVal = RetVal.Substring(0, RetVal.Length - 2);
                    RetVal += "}";
                    RetVal += Environment.NewLine;


                }
                else if (o.GetType().IsClass && !(o is string))
                {
                    //Instantz einer Klasse                              
                    foreach (MemberInfo M in o.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance))
                    {
                        PropertyInfo P = M as PropertyInfo;
                        FieldInfo f = M as FieldInfo;
                        if (P != null || f != null)
                            RetVal += M.Name + " = " + Dump(f != null ? f.GetValue(o) : P.GetValue(o, null));
                    }
                    RetVal += Environment.NewLine;


                }
                else
                    if (o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).Length != 0)
                    {
                        //Struct
                        FieldInfo[] FI = o.GetType().GetFields();
                        RetVal += "[";
                        foreach (FieldInfo f in FI)
                        {
                            RetVal += f.Name + " = " + f.GetValue(o) + Environment.NewLine;
                        }
                        RetVal = RetVal.Remove(RetVal.Length - 2);
                        RetVal += "]" + Environment.NewLine;
                    }

                    else
                    {
                        //Type
                        RetVal += o.ToString() + Environment.NewLine;

                    }

                return RetVal;
            }
            catch (Exception ex)
            {
                return "Fehler beim verarbeiten: " + ex.Message;
            }
        }



    }

}


mfg Flitzs


Moderiert von user profile iconChristian S.: Topic aus C# - Die Sprache verschoben am Do 19.06.2008 um 23:49


Zuletzt bearbeitet von Flitzs am Fr 20.06.08 00:30, insgesamt 1-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Do 19.06.08 23:49 
Ist schon spät, daher guck ich mir das genauer erst morgen an. :-)

Auf jeden Fall eine sehr nützliche Funktion :zustimm:

Was mir direkt auffällt: Ich würde zum einen einen StringBuilder verwenden, welchen Du für die Rekursion auch als Parameter an die Funktion übergeben können solltest. Das sollte schneller sein und weniger Speicher verbrauchen als mit Strings zu arbeiten.

Außerdem würde ich versuchen, ein paar Caching-Funktionen einzubauen. So braucht man für einen Typ ja nur einmal die PropertyInfos abrufen, die kann man ja dann cachen.

//edit:
Noch eine weitere Idee: Man cached nicht nur die PropertyInfos, sondern cached für jeden Typ die komplette Methode, nach der er serialisiert wird. Man definiert einen solchen Delegate:
ausblenden C#-Quelltext
1:
private delegate void SerializeDelegate(Object o, StringBuilder sb);					

und hat ein Dictionary:
ausblenden C#-Quelltext
1:
private Dictionary<Type, SerializeDelegate> serializers;					

Dann braucht man die ganzen Fall-Unterscheidungen nur einmal pro Typ machen, ab da ruft man nur noch den korrekten Delegate aus dem Dictionary ab.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Fr 20.06.08 13:08 
Danke für deine Antwort.
Das mit den StringBuilder hab ich mal so gemacht, allerdings hab ich den Global in der Klasse deklariert damit ich den nicht jedesmal als Parameter übergeben muss.

Ja das mit dem Chachen muss ich mir noch überlegen wie ich das mache, noch hab ich keine Idee wie ich das anstelle :D

mfg Flitzs

PS: Aktueller Code:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
using System;
using System.Reflection;
using System.Collections;

namespace OD
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Collections.Generic.List<String> a = new System.Collections.Generic.List<string>() { "eins""zwei""drei" };
            Console.WriteLine(ObjectDumper.Write(a));
            Console.ReadLine();
        }
    }
    public static class ObjectDumper
    {
        private static System.Text.StringBuilder SB;
        private static Boolean Err;
        private static String ErrMessage;
        /// <summary>
        /// Gibt das Objekt als String zurück
        /// </summary>
        /// <param name="o">Das Objekt</param>
        /// <returns></returns>
        public static string Write(object o)
        {
            SB = new System.Text.StringBuilder();
            ErrMessage = "";
            Err = false;
            Dump(o);
            return (!Err) ? SB.ToString() : ErrMessage ;
        }
        
        
        private static void Dump(object o)
        {
                        
            if (o == null || Err == truereturn;

            try //Nicht gerade optimal aber mit fällt nichts besseres ein, da es abundzu Fehler gibt die ich sonst nicht abfangen kann.
            {

                if (o is IEnumerable && !(o is ValueType) && !(o is string))
                {
                    //IEnumerable
                    SB.Append("{");
                    
                    foreach (object Item in (IEnumerable)o)
                    {
                        Dump(Item);

                        if (Item is string)
                        {
                            SB.Remove(SB.ToString().Length - 2,2);
                            SB.Append(", ");
                        }
                    }
                    if (SB.ToString().Length > 1)
                        SB = new System.Text.StringBuilder(SB.ToString().Substring(0, SB.ToString().Length - 2));
                    SB.Append ("}" + Environment.NewLine);


                }
                else if (o.GetType().IsClass && !(o is string))
                {
                    //Instantz einer Klasse                              
                    foreach (MemberInfo M in o.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance))
                    {
                        PropertyInfo P = M as PropertyInfo;
                        FieldInfo f = M as FieldInfo;
                        if (P != null || f != null)
                            SB.Append(M.Name + " = ");
                            Dump(f != null ? f.GetValue(o) : P.GetValue(o, null));
                    }
                      SB.Append(Environment.NewLine);


                }
                else
                    if (o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).Length != 0)
                    {
                        //Struct
                        FieldInfo[] FI = o.GetType().GetFields();
                           SB.Append("[");
                        foreach (FieldInfo f in FI)                        
                         SB.Append(f.Name + " = " + f.GetValue(o) + Environment.NewLine);
                        
                        SB.Remove(SB.ToString().Length - 2,2);
                         SB.Append("]" + Environment.NewLine);
                    }

                    else
                    {
                        //Type
                        SB.Append(o.ToString() + Environment.NewLine);

                    }
            }
            catch (Exception ex)
            {
                Err = true;
                ErrMessage = "Fehler beim verarbeiten: " + ex.Message;
                return;
            }
        }



    }

}
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 20.06.08 14:18 
user profile iconFlitzs hat folgendes geschrieben:
Ja der Sinn für die dies nicht kennen, ein Objekt mit sämtlichen Members die interresant sind, über reflection, als String zurückgeben.
Also einfach eine proprietäre Variante von JSON :tongue: ? Nichts für ungut, aber da muss ich eben gleich an Not Invented Here denken ;) . Als Übung aber z.B. wahrscheinlich perfekt, du zwingst mich geradezu zu einer F#-Implementierung :D .

PS: Ich denke, du meinst den ObjectDumper aus den C#-Samples. Sitzt im VS-Verzeichnis unter "Microsoft Visual Studio 9.0\Samples\1031\CSharpSamples.zip\LinqSamples\ObjectDumper".
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Fr 20.06.08 14:30 
Jop den meinte ich, ich hab ihn damals bei einer Microsoft Presentation der C# 3 new Feature gesehen. Ähm jo hätte ich früher gewusst das es den eh schon als sample gibt hätt ichs wohl gelassen aber so is es ne gute Übung zudem will ich ja noch das von Christian S. angesprochene Chachen einbauen ;)

mfg Flitzs