程序中通常會有一些錯誤代碼或標識,為了程序中方便這些東西通常不會使用漢字,經常在程序中用的是一些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>