Reflection basierte string Repräsentation für beliebige Objekte

Thomas Darimont

Erfahrenes Mitglied
Hallo,

für java gibts mit dem ToStringBuilder aus dem jakarta commons lang ( http://jakarta.apache.org/commons/lang/ ). Dieser bietet eine Methode reflectionToString an mit dem man eine String Repräsentation eines beliebigen Objektes erzeugen kann.

Unter codeplex findet man mit den DotnetCommons den Begin eines Ports aber der sieht noch sehr nach work in progress aus...
http://www.codeplex.com/DotnetCommons

Weiterhin enthält der dortige ToStringBuilder die entsprechende Methode leider nicht..

Dafür hat die Klasse Dotnet.Commons.Reflection.ObjectUtils sowas ähnliches:
http://www.codeplex.com/DotnetCommons/SourceControl/FileView.aspx?itemId=54097&changeSetId=3655

Hier deshalb mal ne eigene kleine Variante (die auch rekursiv wieder in die Properties reinschaut und auch von denen die ToString Repräsentation erzeugt)
Ob nun nur Fields oder nur Properties angeschaut werden kann dabei konfiguriert werden. Weiterhin kann man auch konfigurieren, ob ToString() Implementierungen beachtet werden sollen oder nicht:

Unser Beispiel:
C#:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

namespace De.Tutorials.Training
{

    public class StringUtilsTest
    {
         public static void Main(string[] args)
        {
  
            IList<string> strings = new List<string>();
            strings.Add("AA");
            strings.Add("BB");
            strings.Add("CC");

            IDictionary<string, int> map = new Dictionary<string, int>();
            map.Add("XXX", 3);
            map.Add("YYYY", 4);

            IList list = new ArrayList();
            list.Add("bubu");
            list.Add(strings);
            list.Add(map);
            list.Add(null);
            list.Add(4711);
            list.Add(map);
            list.Add(new StringUtilMock((IList)strings, 9994));

            StringUtilMock mock = new StringUtilMock(list, 123456);

            Console.WriteLine(ToStringBuilder.ReflectionToString(mock,true,false));
        }

    }

    public class StringUtilMock
    {
        private IList list;

        public IList List
        {
            get { return list; }
            set { list = value; }
        }

        private int data;

        //public int Data
        //{
        //    get { return data; }
        //    set { data = value; }
        //}

        public StringUtilMock(IList list, int data)
        {
            this.list = list;
            this.data = data;
        }

        public override string ToString()
        {
            return data + " list -> size: " + list.Count;
        }
    
    }
}

Ausgabe: mit Console.WriteLine(ToStringBuilder.ReflectionToString(mock,true,false));
Code:
StringUtilMock<List=[bubu,[AA,BB,CC],{XXX:3,YYYY:4},null,4711,{XXX:3,YYYY:4},StringUtilMock<List=[AA,BB,CC]>]>

Ausgabe: mit Console.WriteLine(ToStringBuilder.ReflectionToString(mock,true,true));
Code:
123456 list -> size: 7

Ausgabe: mit Console.WriteLine(ToStringBuilder.ReflectionToString(mock,false,false));
Code:
StringUtilMock<list=[bubu,[AA,BB,CC],{XXX:3,YYYY:4},null,4711,{XXX:3,YYYY:4},StringUtilMock<list=[AA,BB,CC],data=9994>],data=123456>


Ausgabe: mit Console.WriteLine(ToStringBuilder.ReflectionToString(mock,false,true));
Code:
StringUtilMock<list=[bubu,[AA,BB,CC],{XXX:3,YYYY:4},null,4711,{XXX:3,YYYY:4},StringUtilMock<list=[AA,BB,CC],data=9994>],data=123456>

Hier der ToStringBuilder:
C#:
using System;
using System.Collections;
using System.Text;
using System.Reflection;

namespace De.Tutorials.Training
{
    public class ToStringBuilder
    {

        private bool onlyProperties;

        public bool OnlyProperties
        {
            get { return onlyProperties; }
            set { onlyProperties = value; }
        }

        private bool respectToStringMethod;

        public bool RespectToStringMethod
        {
            get { return respectToStringMethod; }
            set { respectToStringMethod = value; }
        }


        public ToStringBuilder(bool onlyProperties, bool respectToStringMethod)
        {
            this.onlyProperties = onlyProperties;
            this.respectToStringMethod = respectToStringMethod;
        }

        public string ToString(IList list)
        {
            StringBuilder stringBuilder = new StringBuilder("[");
            int count = 0;

            for (int index = 0; index < list.Count; index++)
            {
                stringBuilder.Append(ToString(list[index]));
                if (++count < list.Count)
                {
                    stringBuilder.Append(",");
                }
            }
            stringBuilder.Append("]");
            return stringBuilder.ToString();
        }

        public string ToString(object o)
        {
            if (null == o)
            {
                return "null";
            }

            if (o is ValueType)
            {
                return o.ToString();
            }

            if (o is string)
            {
                return (string)o;
            }

            if (respectToStringMethod)
            {
                return o.ToString();
            }
            
            else if (o is IList)
            {
                return ToString((IList)o);
            }
            else if (o is IDictionary)
            {
                return ToString((IDictionary)o);
            }
            else
            {
                if (o.GetType() != typeof(object))
                {
                    return InternalReflectionToString(o);
                }
                else
                {
                    return o.ToString();
                }
            }
        }

        public string ToString(IDictionary dictionary)
        {
            StringBuilder stringBuilder = new StringBuilder("{");
            int count = 0;

            foreach (object key in dictionary.Keys)
            {
                string keyString = ToString(key);
                string valueString = ToString(dictionary[key]);

                stringBuilder.Append(keyString);
                stringBuilder.Append(":");
                stringBuilder.Append(valueString);

                if (++count < dictionary.Keys.Count)
                {
                    stringBuilder.Append(",");
                }
            }

            return stringBuilder.Append("}").ToString();
        }

        private const System.Reflection.BindingFlags ALL_INSTANCE_BOUND_FIELDS = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic;

        public static string ReflectionToString(object o)
        {
            return ReflectionToString(o, false, false);
        }

        private string InternalReflectionToString(object o)
        {
            Type type = o.GetType();

            StringBuilder stringBuilder = new StringBuilder(type.Name);
            stringBuilder.Append("<");

            int count = 0;

            if (onlyProperties)
            {
                PropertyInfo[] properties = type.GetProperties(ALL_INSTANCE_BOUND_FIELDS);
                foreach (PropertyInfo propertyInfo in properties)
                {
                    HandleMember(stringBuilder, propertyInfo.Name, propertyInfo.GetValue(o, null));
                    if (++count < properties.Length)
                    {
                        stringBuilder.Append(",");
                    }
                }
            }
            else
            {
                FieldInfo[] fields = type.GetFields(ALL_INSTANCE_BOUND_FIELDS);
                foreach (FieldInfo fieldInfo in fields)
                {
                    HandleMember(stringBuilder, fieldInfo.Name, fieldInfo.GetValue(o));
                    if (++count < fields.Length)
                    {
                        stringBuilder.Append(",");
                    }
                }
            }

            stringBuilder.Append(">");

            return stringBuilder.ToString();

        }

        public static string ReflectionToString(object o, bool onlyProperties,bool respectToStringMethod)
        {
            if (null == o)
            {
                return "null";
            }

            return new ToStringBuilder(onlyProperties, respectToStringMethod).ToString(o);
        }

        private void HandleMember(StringBuilder stringBuilder, string memberName, object value)
        {
            stringBuilder.Append(memberName);
            stringBuilder.Append("=");
            stringBuilder.Append(ToString(value));
        }
    }
}
Hab jedoch noch Probleme mit indexed Properties
C#:
public virtual object this[int index] { get; set; }
... ist mit aber jetzt zu fummelig :p Wer will kann das ja fixen...

Gruß Tom
 
Zurück