code it

Martins Tech Blog

In die JSON-Serialisierung eingreifen

Der Anwendungsfall

In einer Seite sollen Diagramme angezeigt werden. Für die Darstellung habe ich mich für flot entschieden. Dabei handelt es sich um eine JavaScript-Bibliothek, die in einem Platzhalter mit Hilfe von Canvas-Elementen Charts in diversen Formaten zeichnen kann. 

Im ersten Beispiel soll ein Tortendiagramm erzeugt werden. 

Die Datenstruktur ist dabei recht simpel. Es handelt sich um ein Array von Objekten mit jeweils einem Label und einem Zahlenwert für die Daten.

var pieData = [{ label: "geschieden", data: 5 }, { label: "verheiratet", data: 25 }, { label: "ledig", data: 30 }];
$.plot($("#myChart"), pieData, {
    series: {
        pie: {
            show: true
        }
    },
    grid: {
        hoverable: true
    },
    legend: {
        labelBoxBorderColor: "none"
    }
});

Im zweiten Beispiel soll ein Liniendiagramm erzeugt werden, das Werte mehrerer Serien über einen Zeitraum darstellen kann.

Die Datenstruktur ist ähnlich wie die des Tortendiagramms. Nur nun enthält data nicht mehr einen einzelnen Wert, sondern ein Array von x-y-Werten. das Beispiel beinhaltet die Daten vom 01.11. bis 03.11.2012. Die x-Achse ist auf den Zeitraum 31.10. bis 04.11. arretiert, damit der erste Datenwert nicht direkt am Rand des Charts liegt.

var lineData = [
    { label: "aktive Kunden", data: [[1351724400000, 213], [1351810800000, 215], [1351897200000, 217]] },
    { label: "Support Tickets", data: [[1351724400000, 100], [1351810800000, 80], [1351897200000, 70]] }
];
$.plot($("#myChart"), lineData, {
    xaxis: {
        mode: "time",
        min: new Date(2012, 09, 31).getTime(),
        max: new Date(2012, 10, 4).getTime(),
    },
    yaxis: {
        tickDecimals: 0,
        min: 0,
        max: 300
    },
    series: {
        lines: { show: true },
        points: {
            radius: 3,
            show: true,
            fill: true
        }
    },
    grid: {
        hoverable: true
    },
    legend: {
        labelBoxBorderColor: "none"
    }
});

So weit so gut. Mehr...

Lokalisierung von Enumerationen

Bei der Entwicklung mehrsprachiger Anwendungen kommt man meist auch an die Stelle, in der Enumerationen lokalisiert werden sollen. In meinem Beispiel ist das der Status eines Artikels. Das Enum ist wir folgt definiert:

public enum ArticleStatus
{
    Active = 0,
    Inactive = 1,
    Deleted = 2
}

Das Objekt Artikel selbst hat eine entsprechende Eigenschaft, in der der Status dargestellt wird.

public ArticleStatus Status
{
    get { return this.status; }
    set { this.status = value; }
}

Was in rein englischsprachigen Anwendungen mit article.Status.ToString() noch recht einfach ist, stellt sich in multilangualen Anwendungen schon schwieriger dar. Wie bekommt man die String-Repräsentation mehrsprachig? Eine sehr elegante und variable Möglichkeit ist die Verwendung von Enumconvertern. Diese bieten als zusätzliches Goodie Design-Time-Support, aber das nur als Randbemerkung. Der erste Schritt ist die Erzeugung einer neuen Konverter-Klasse. Diese erbt von EnumConverter. Die eigentliche Konvertierung nimmt die überschriebene Methode ConvertTo vor.

internal class ArticleStatusConverter : EnumConverter
{
    public ArticleStatusConverter(Type type) : base(type) { }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (value != null && destinationType == typeof(string))
        {
            ArticleStatus objectToConvert = (ArticleStatus)value;
            CultureInfo currentCulture = culture jQuery1520972166896564886_1309626526281 CultureInfo.CurrentCulture;

            return MyResourceManager.getLocalizedText(string.Concat("ArticleStatus_", (int)value), currentCulture)
        }
        else
        {
            return base.ConvertTo(context, culture, value, destinationType);
        }

    }
}

Damit die Methode jetzt verwendet werden kann, muss zunächst dem Enum per Attribut der EnumConverter zugewiesen werden.

[TypeConverter(typeof(ArticleStatusConverter))]
public enum ArticleStatus
{
    ...
}

Nun könnte man davon ausgehen, dass dadurch .ToString()  auch gleich überschreiben wurde. Das ist aber nicht der Fall. Der Code, um auf die eben implementierte Funktionalität zugreifen zu können, ist etwas komplizierter, aber dennoch logisch:

string statusAsString = (string)TypeDescriptor
    .GetConverter(typeof(ArticleStatus))
    .ConvertTo(article.Status, typeof(string));