Laden...

Enum, Datenstruktur für Fehlercodes [Lokalisierung]

Erstellt von snoop83 vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.915 Views
S
snoop83 Themenstarter:in
46 Beiträge seit 2006
vor 14 Jahren
Enum, Datenstruktur für Fehlercodes [Lokalisierung]

Hallo,

ich bin auf der Suche nach einer geeigneten Struktur für Fehlercodes. Bisher habe ich das wie folgt gehandhabt:

public enum ErrorCodes
{
  WEBEXCEPTION = 100,
  WEBTIMEOUT = 101,
  WEBURINOTFOUND = 102,

  THREADEXCEPTION = 200,

  FILENOTFOUND = 300,
  DIRNOTFOUND = 301,
  DIRNOTACCESSABLE = 303,
  ...
}

Nun brauche ich derzeit passend zu den jeweiligen Fehlercodes lokalisierte Fehlertexte. Ein Ansatz wäre folgender:


public string GetText(ErrorCodes code)
{
  switch (code)
  {
     case ErrorCodes.WEBEXCEPTION:
       return Properties.Resources.ERR_WEBEXCEPTION;
     case ErrorCodes.WEBTIMEOUT:
       return Properties.Resources.ERR_WEBTIMEOUT;
     ....
  }
}

Die lokalisierten Texte liegen also in Resourcendateien, was ich sehr aufwändig in der Wartung finde (Texte können in Sprachen vergessen werden ohne dass man es merkt).

Ein anderer Ansatz wäre dieser:


public string GetText(ErrorCodes code)
{
  string lang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.ToLower();
  switch (code)
  {
     case ErrorCodes.WEBEXCEPTION:
       if (lang.Equals("de")) return "Unbekannter Fehler bei ...";
	   if (lang.Equals("en")) return "Unknown error during ...";
     case ErrorCodes.WEBTIMEOUT:
       if (lang.Equals("de")) return "Zeitüberschreitung der Internetverbindung";
	   if (lang.Equals("en")) return "Timeout error of internet connection");
     ....
  }
}

Auch hier kann ich div. Texte vergessen.

Ich würde bei der Definition der Fehlercodes gern bei einem enum bleiben (da ich hier sichergehen kann, dass Fehlercodes nur einmal vergeben werden und der Zugriff sehr einfach von überall möglich ist).

Ich habe nun daran gedacht, das enum durch ein struct zu ersetzen und dort die entsprechenden Informationen abzulegen, was den Vorteil hätte, dass keine Informationen fehlen können und sämtliche Texte in einer Datei stehen. Mein Ansatz:

public struct ErrorCode
{
	private int code;
	private string langDE;
	private string langEN;

	public int Code { get { return this.code; } }
	public string LangDE { get { return this.langDE; } }
	public string LangEN { get { return this.LangEN; } }

	public ErrorCode(int pCode, string pLangDE, string pLangEN)
	{
		this.code = pCode;
		this.langDE = pLangDE;
		this.langEN = pLangEN;
	}
}

public static class ErrorCodes
{
	public static ErrorCode WEBSERVICE_EXC
	{
		get { return new ErrorCode(100, "Fehler bei ..", "Error during .."); }
	}

	public static ErrorCode THREAD_EXC
	{
		get { return new ErrorCode(200, "Fehler bei ...", "Error during ..."); }
	}
}

Nachteil hier: Ich kann (aus Versehen) Fehlercodes doppelt vergeben. Man stelle sich ein sehr lange Liste von Fehlern vor, wo ich durchaus die Zahl 300 mehrfach vergeben kann.

Kennt jemand eine elegantere Lösung zur Verwaltung von Fehlercodes und lokalisierten Fehlertexten?

S
snoop83 Themenstarter:in
46 Beiträge seit 2006
vor 14 Jahren

Als Anmerkung ... in Java kann ich folgendes machen:


public class Errors {

    public enum Error {
        Unknown(1, "??", "??"),
        WEBEXCEPTION(100, "Fehler bei Zugriff auf Internetverbindung", "Error during internet connection"),
        WEBTIMEOUT(101, "Zeitüberschreitung der Internetverbindung", "Timeout error of internet connection"),
        ;
        

        
        private int value;
        private String de_De;
        private String en_GB;

        private Error(int value, String de_De, String en_GB) {
            this.value = value;
            this.de_De = de_De;
            this.en_GB = en_GB;
        }

        public String getDe_De() {
            return de_De;
        }

        public String getEn_GB() {
            return en_GB;
        }

        public int getValue() {
            return value;
        }

        public void setDe_De(String de_De) {
            this.de_De = de_De;
        }

        public void setEn_GB(String en_GB) {
            this.en_GB = en_GB;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }

    private static Error findByValue(int value) {
        for (final Error code : Error.values()) {
            if (value == code.value) {
                return code;
            }
        }
        return null;
    }
    public static String getErrorCode(int value, String localeValue) {
        final int locale = Locale.getLocale(localeValue);
        switch (locale) {
            default:
            case Locale.LOCALE_DE_DE: {
                final Error code = findByValue(value);
                return code == null ? "???" : code.getDe_De();
            }
            case Locale.LOCALE_EN_GB: {
                final Error code = findByValue(value);
                return code == null ? "???" : code.getEn_GB();
            }
        }
    }
    
}

So etwas in der Art hätte ich gern

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo snoop83,

ich habe ehrlich gesagt nicht alles gelesen. Ich kann aber sagen, dass man in C# normalerweise eigene Exception-Klassen definieren würde.

herbivore

U
1.578 Beiträge seit 2009
vor 14 Jahren

boese

  1. man sollte nicht alle texte irgendwo im code haben
  2. man sollte zudem nicht alle uebersetzten texte zusaetzlich halten
  3. es sollte nur eine zentrale schnittstelle geben die regelt welche sprachen es gibt und je nach eingestellter culture die entsprechenden strings liefert

erstell eine "strings datei" - bei wpf eine resource dictionary bei allen anderen kanns auch eine xml sein

also

Strings-en-US.xml
Strings-en-UK.xml
Strings-de-DE.xml
...

beide haben intern die selbe struktur, nur das es halt jeweils ein einer anderen sprache ist

zb
Strings-en-US.xml
<Error code="100">Error during internet connection</Error>
Strings-de-DE.xml
<Error code="100">Fehler bei Zugriff auf Internetverbindung</Error>

im code dann hast du eine zentrale schnittstelle - ich nenn sie mal "Translator"

die bietet folgende methode:


public static string GetErrorMessage(int code)
{
    // Open xml by culture
    // return inner text
}

und spaeter dann

throw new WebException(Translator.GetErrorMessage(100));

und je nach eingestellter Culture bekommst du die jeweilige message zurueck
nun brauchst du nur deine Strings-en-US.xml zu pflegen, und diese dann kopieren und einfach uebersetzen

im translator kannst du ja beim ersten aufruf den inhalt der xml dateien in ein dictionary packen - dir ueberlassen
evtl noch eine fallback datei falls ein code in der deutschen datei fehlt


public static string GetErrorMessage(int code)
{
    if (dic.Count == 0)
        LoadDic(LoadFile(Thread.CurrentThread.CurrentCulture));
    if (!dic.ContainsKey(code))
        return fallBackDic[code];
    return dic[code];
}

//dazuedit, warum werden meine [] klammern zwei zeilen tiefer angezeigt ?

S
snoop83 Themenstarter:in
46 Beiträge seit 2006
vor 14 Jahren

@ herbivore:
Wenn ich einen WebService aufrufe, den Aufruf entsprechend absichere, reicht doch für den Benutzer eine einfache Meldung "Achtung, beim Webaufruf ist etwas schief gelaufen". Sicherlich könnte man hier eine eigene Exception-Klasse erstellen und die wirklich aufgetretene Exception als InnerException ablegen, aber mir geht es in diesem Fall rein um die Verwaltung von lokalisierten Fehlermeldungen, vielleicht gibt es da ja einen besseren Ansatz.

@ Mr Evil:
Die Lösung mittels xml-Datei ist ja im Prinzip die gleiche, als wenn ich die Resourcen-Dateien von Visual Studio nehme.

Fakt ist doch, dass ich bei beiden Lösungen sehr schnell auf die Nase fallen kann, wenn eine neue Nachricht dazukommt und ich in irgendeiner Sprache vergesse, diese hinzuzufügen. Dort habe ich dann keine Chance, das zur Compilzeit herauszufinden (außer natürlich pre- oder post-Buildscript).

Ich hätte gern eine Lösung bei der ich auch sicher gehen kann, dass wirklich alles übersetzt wurde.

D
500 Beiträge seit 2007
vor 14 Jahren

Hallo,

alternativ, wenn man Enums uebersetzen moechte, finde ich folgenden Beitrag auch ganz gut: Localizing .Net Enumerations

Gruss, DaMoe

S
snoop83 Themenstarter:in
46 Beiträge seit 2006
vor 14 Jahren

@ DaMoe80:
Das gefällt mir doch schon ganz gut! Ich kann die Vorteile von Enums nutzen und brauche keinen (speziellen) Code für die Lokalisierung zu schreiben.

Einzig verbleibendes Problem: Die penible Pflege der Resource-Datei 😉

U
1.578 Beiträge seit 2009
vor 14 Jahren

die pflege der resource datei hast du immer
du musst dir ein fallback einbauen - was soll passieren wenn es von einem item keine uebersetzung gibt
die normale herangehensweise ist dannd as englische zu zeigen - eine debug message kannst du dann ja auch noch ausgeben