程序中通常會有一些錯誤代碼或標識,為了程序中方便這些東西通常不會使用漢字,經常在程序中用的是一些FileError或數字。還有就是在編碼中經常使用的枚舉標識對象的狀態。而通常這些信息會直接的或間接的現實給用戶,可用戶需要到的是容易理解的漢字描述。以前要麼將這些標識和枚舉的轉換規則硬編碼到程序中,要麼就直接提示給用戶。前者沒有很好的擴展性,而後者則讓用戶一頭霧水。現可以用流行的XML(配置文件)保存提示信息,然後用一個對象將機器中的內碼轉換為人們容易理解的信息。
轉換對象如下:


/**//// <summary>

/// 翻譯類,將內部碼翻譯成容易理解的中文

/// </summary>

/// <remarks>

/// 根據配置文件中的信息,將系統內部碼(錯誤碼、成功碼)翻譯成中文(或人容易理解的語言)。

/// </remarks>

public static class Translation


...{

private static System.IO.FileSystemWatcher watcher;

private static XMLDocument content;

private static string configFile;

private static object locker = new object();



/**//// <summary>

/// 加載配置文件

/// </summary>

/// <param name="configFile"></param>

public static void Configure(string configFile)

...{

LoadFile(configFile);

if (watcher != null)


...{

watcher.Dispose();

}

watcher = new FileSystemWatcher(Path.GetDirectoryName(configFile), Path.GetFileName(configFile));

watcher.Changed += new FileSystemEventHandler(watcher_Changed);

}



/**//// <summary>

/// 加載默認配置文件

/// </summary>

public static void Configure()


...{

if (System.Web.HttpContext.Current != null)

...{

Configure(System.Web.HttpContext.Current.Server.MapPath("~/translation.config"));

}

else


...{

Configure(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "\" + "translation.config");

}

}



/**//// <summary>

/// 加載文件內容

/// </summary>

/// <param name="configFile"></param>

private static void LoadFile(string configFile)


...{

lock (locker)


...{
XmlDocument doc = new XMLDocument();

doc.Load(configFile);


content = doc;

Translation.configFile = configFile;

}

}



/**//// <summary>

/// 當文件變更時,從新加載文件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private static void watcher_Changed(object sender, FileSystemEventArgs e)


...{

LoadFile(configFile);

}



/**//// <summary>

/// 獲取Enum的解釋,如果Enum有Flag標記,則使用逗號分隔各個解釋

/// </summary>

/// <param name="enumValue"></param>

/// <returns></returns>

public static string GetEnumDescription(Enum enumValue)


...{

return GetEnumDescription(enumValue, ",");

}



/**//// <summary>

/// 獲取Enum的解釋,如果Enum有Flag標記,則使用sparator分隔各個解釋

/// </summary>

/// <param name="enumValue"></param>

/// <param name="sparator"></param>

/// <returns></returns>

public static string GetEnumDescription(Enum enumValue, string sparator)


...{

Type type = enumValue.GetType();


//檢查類型是否有Flags特性

object[] attrs = type.GetCustomAttributes(typeof(FlagsAttribute), false);

if (attrs.Length > 0)
...{

StringBuilder builder = new StringBuilder();

Array arr = Enum.GetValues(type);

foreach (Enum enu in arr) //循環獲取每一個值的解釋


...{

if ((Convert.ToUInt64(enumValue) & Convert.ToUInt64(enu)) == Convert.ToUInt64(enu)) //判斷是否有這個值


...{

builder.Append(GetEnumDes(type, enu.ToString()));

builder.Append(sparator);

}

}

if (builder.Length != 0) //拿掉最後的分隔符

builder.Remove(builder.Length - sparator.Length, sparator.Length);

return builder.ToString();

}

else
...{

return GetEnumDes(type, enumValue.ToString());

}

}



/**//// <summary>

/// 獲取某一Enum類型值的解釋

/// </summary>

/// <param name="type"></param>

/// <param name="value"></param>

/// <returns></returns>

private static string GetEnumDes(Type type, string value)


...{

string xquery = "/translation/enum/" + type.FullName + "/" + value;

XMLNode node = content.SelectSingleNode(xquery);

if (node != null)

return node.InnerText;

else

return value;

}


/**//// <summary>

/// 翻譯指定值

/// </summary>

/// <param name="obj"></param>

/// <returns></returns>

public static string GetValueDescription(object obj)


...{

return GetValueDescription("default", obj);

}



/**//// <summary>

/// 在指定組中翻譯指定值

/// </summary>

/// <param name="group"></param>

/// <param name="obj"></param>

/// <returns></returns>

public static string GetValueDescription(string group, object obj)


...{

if (obj == null)

return "null";


string xquery = "/translation/description[@group='" + group + "']/add[@key='" + obj.ToString() + "']/@value";

XMLNode node = content.SelectSingleNode(xquery);

if (node == null)

return obj.ToString();

else

return node.Value;

}

}

在這個對象使用前需要使用Configure方法來加載xml配置文件,默認的配置文件名稱為translation.config。轉換對象使用單例模式,使用了一個FileSystemWatcher對象來監視XML文件,如果XML有變化,則從新加載。查詢XML使用了XPath表達式。
然後即可使用GetEnumDescription和GetValueDescription方法來翻譯枚舉和標識了。如果沒有找到可以翻譯的值,則會返回對象的ToString方法的返回值。
示例XML配置:

<?XML version="1.0" encoding="utf-8" ?>

<translation>

<enum>

<!--此出要用枚舉的全名-->

<Library.UserType>

<Unknow>未知</Unknow>

<AfterPayUser>後付費用戶</AfterPayUser>

<BeforePayUser>預付費用戶</BeforePayUser>

</Library.UserType>

</enum>


<description group="default">

<add key="FileErrorl" value="文件已損壞" />

</description>


<description group="skin">

<add key="Default" value="默認皮膚" />

</description>


<description group="topic">

<add key="space" value="<span class='red'>您剩余的空間不足,請您刪除部分文件。</span><br/>" />

<add key="yue" value="<span class='red'>您的余額不足,請盡快充值。</span><br />" />

</description>

</translation>