using System;
using System.Threading;

class Name : IFormattable
{
    public string firstname;
    public string secondname;

    public Name(string firstname, string secondname)
    {
        this.firstname = firstname;
        this.secondname = secondname;
    }

    public override string ToString() { return ToString(null, null); }

    public string ToString(string format)
    {
        return ToString(format, null);
    }

    public string ToString(IFormatProvider fp)
    {
        return ToString(null, fp);
    }

    public string ToString(string format, IFormatProvider fp)
    {
        // kein Format
        if (format == null)
            return String.Format("{0} {1}", firstname, secondname);

        // "g"-Format
        if (format == "g" || format == "G")
            return String.Format("{0} {1}", firstname, secondname);

        // "i"-Format, erst Familienname, dann Vorname)
        if (format == "i" || format == "I")
            return String.Format("{0}, {1}", secondname, firstname);

        // "s"-Format, nur Nachname
        if (format == "s" || format == "S")
            return secondname;

        // Nicht unterstützte Formate
        throw new FormatException(String.Format("Ungültiger Formatbezeichner: '{0}'.", format));
    }
}

sealed class SpecialXMLFormatter : IFormatProvider, ICustomFormatter
{
    public Object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;

        return Thread.CurrentThread.CurrentCulture.GetFormat(formatType);
    }

    public string Format(String format, Object arg, IFormatProvider formatProvider)
    {
        string s;

        IFormattable formattable = arg as IFormattable;

        if (formattable == null)
            s = arg.ToString();
        else
            s = formattable.ToString(format, formatProvider);

        // Hier werden die Typen Int32 und Name nachformatiert
        if (arg.GetType() == typeof(Name))
            return "<name>" + s + "</name>";
        if (arg.GetType() == typeof(Int32))
            return "<age>" + s + "</age>";

        return s;
    }
}

class ICustomFormatterDemo
{
    static void Main()
    {
        Name name = new Name("Leopold", "Bloom");
        int age = 48;

        string s = String.Format(" {0:I} ist {1} Jahre alt.", name, age);
        Console.WriteLine(s);

        s = String.Format(new SpecialXMLFormatter(), " {0:I} ist {1} Jahre alt.", name, age);
        Console.WriteLine(s);
    }
}
