上层模块调用底层模块的接口,返回错误代码的时候,如果采用这种方式:
public const int ERR_0 = 0; public const int ERR_1 = 1; public class ShellExcuteResult { public int Code { get; set; } public string Output { get; set; } public string Error { get; set; } } static ShellExcuteResult shellExcute_0() { ShellExcuteResult result = new ShellExcuteResult(); result.Code = ERR_1; result.Output = "Success"; result.Error = "pkg 6kb/s"; return result; } public const int INSTALL_SUCCESS = 0; public const int INSTALL_FAIL = 1; static int install_0() { ShellExcuteResult result = shellExcute_0(); if (result.Code == ERR_0) { return INSTALL_SUCCESS; } else { return INSTALL_FAIL; } }
将造成了信息的丢失,调用install接口的只知道安装成功或者失败,而无法得到失败的原因。也正是因为如此,要写LOG的时候会非常麻烦,因为往往是在上层模块的接口调用失败的时候需要写LOG,但是在失败的地方,却得不到足够的信息,只能在底层也写LOG。
一个合适的做法是,像Exception的栈一样,为Error带上信息栈。
abstract class LxError { private LxError mInnerError; public LxError() : this(null) { } public LxError(LxError innerError) { mInnerError = innerError; } public abstract Object Data { get; } public LxError InnerError { get { return mInnerError; } } public string Source { get; set; } public string Message(string prefix) { return RMessage("", prefix); } protected string RMessage(string prefix1, string prefix2) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(this.MessageString(prefix1)); if (mInnerError != null) { stringBuilder.Append("\n"); stringBuilder.Append(mInnerError.RMessage(prefix1 + prefix2, prefix2)); } return stringBuilder.ToString(); } public abstract string MessageString(string prefix); protected StringBuilder BaseMessageStringBuilder(string prefix) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(prefix).Append("Source : ").Append("\"").Append(Source).Append("\"").Append("\n"); stringBuilder.Append(prefix).Append("Data : "); return stringBuilder; } } class ShellError : LxError { private Dictionary<string, object> mData = new Dictionary<string, object>(); public override object Data { get { return mData; } } public override string MessageString(string prefix) { StringBuilder stringBuilder = BaseMessageStringBuilder(prefix); if (mData.Count == 0) { stringBuilder.Append("empty"); } else { Dictionary<string, object>.KeyCollection keys = mData.Keys; foreach (string key in keys) { stringBuilder.Append("[").Append(key).Append(":").Append(mData[key]).Append("]"); } } return stringBuilder.ToString(); } } class InstallError : LxError { public const int INSTALL_SUCCESS = 0; public const int INSTALL_FAIL = 1; public const string INSTALL_SUCCESS_STR = "INSTALL_SUCCESS"; public const string INSTALL_FAIL_STR = "INSTALL_FAIL"; public InstallError(ShellError shellError) : base(shellError) { if ((int)((IDictionary)shellError.Data)["code"] == 0) { mData = INSTALL_SUCCESS; } else { mData = INSTALL_FAIL; } } private int mData; public override object Data { get { return mData; } } public override string MessageString(string prefix) { StringBuilder stringBuilder = BaseMessageStringBuilder(prefix); stringBuilder.Append(mData == INSTALL_SUCCESS ? INSTALL_SUCCESS_STR : INSTALL_FAIL_STR); return stringBuilder.ToString(); } } static ShellError shellExcute() { ShellError error = new ShellError(); ((IDictionary)error.Data)["code"] = 1; ((IDictionary)error.Data)["output"] = "Success"; ((IDictionary)error.Data)["error"] = "pkg 6kb/s"; error.Source = "Program : shellExcute"; return error; } static InstallError install() { ShellError shellError = shellExcute(); InstallError error = new InstallError(shellError); error.Source = "Program : install"; return error; }