Søg på DotNyt:
Denne blog er flyttet til www.nielsbrinch.com


søndag den 16. november 2008

Universel ToString med Extension Methods

skrevet af Niels Brinch

Efter at have læst Christian's indlæg som blandt andet handlede om "Pure evil ToString", blev jeg inspireret til at afsløre min egen variant. Start med at læse om "Pure Evil ToString", bare lige lidt, og vend så tilbage til dette indlæg.

...

Ok? Godt.

...

Overordnet handler det om, at man gerne vil kunne skrive en streng ud for et vilkårligt objekt - og det skal være let.

Formålet for "Pure Evil ToString" er tilsyneladende både logging og til at danne strenge til brugergrænsefladen. Problemet med den er til gengæld, at den kan give problemer i runtime, fordi man skal skrive navne på properties i ren tekst som senere kan ændre sig uden compileren opdager sammenhængen.

Formålet med min variant, er udelukkende logging. Den bruger Reflection til at skrive alle oplysninger ud om et objekt og det kan man så logge. Da man ikke angiver præcis hvilke oplysninger man er interesseret i, kan der heller ikke opstå problemer i runtime.

Nok snak. Lad os se på metoden.

public static string GetAsString(object o)

{

    if (o == null)

    {

        return "null";

    }

    else if (o is string)

    {

        return o.ToString();

    }

    else

    {

        Type t = o.GetType();

        System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.FlattenHierarchy;

 

        string output = "ClassName: " + t.Name + Environment.NewLine;

 

        foreach (System.Reflection.FieldInfo info in t.GetFields(flags))

        {

            output += info.Name;

 

            if (info.GetValue(o) != null)

            {

                output += ": " + info.GetValue(o) + Environment.NewLine;

            }

            else

            {

                output += Environment.NewLine;

            }

        }

 

        return output;

    }

}

Eller som Extension Method
Udskift metodens signatur med følgende, for at anvende den som Extension Method.

public static string GetAsString(this object o)

Effekten er, at samtlige objekter i din applikation, har en GetAsString()-metode. Ret bekvemt, synes jeg.

Anvendelse
Den er praktisk at anvende i forbindelse med logging. Jeg kan ikke komme på andre rigtig gode anvendelsesmuligheder. Man kunne måske anvende den til at vurdere om to forskellige objekter indeholder præcis de samme værdier?

Idet der anvendes Reflection, er performance ikke særligt god. Derfor er det vigtigt at man kun anvender metoden til logging OG, at man har indrettet sin logging på en måde, så logging-kald kun bliver kaldt når logging er slået til.

Jeg bruger log4net, så min logging ser ud som nedenstående, men jeg er sikker på du forstår pointen med det, selvom du anvender en anden form for logging.

if (isDebugEnabled)

{

    log.Debug("User: " + user.GetAsString());

}


Den dyre "GetAsString-metode bliver således kun kaldt når logging er slået til.

2 kommentarer

2 Kommentarer:

At 1. december 2008 kl. 13.14, Anonymous Anonym skrev...

Du mangler "this" i den ændrede signatur.

 
At 1. december 2008 kl. 16.44, Blogger Niels Brinch skrev...

Hvor? Det kan jeg da ikke se? :p

(ok ok, jeg har lige rettet det)

 

Send en kommentar

<< Tilbage


 
Til forsiden

Niels Brinch