結構體定義
public struct strRestric
{
public string msgPage; // 頁面顯示訊息
public string msgPrompt; // 提示訊息
public int size; // 最大長度
}
核心解析類別
public class XMLRestrict
{
public static strRestric res;
public XMLRestrict()
{
res.msgPage = "";
res.msgPrompt = "";
res.size = 0;
}
public static object Restrict(string XMLPathName, string nodeID, strRestric res)
{
int NodeNum = 1;
string path = ConfigurationSettings.AppSettings[XMLPathName].ToString();
path += "Restrict.xml";
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
XmlNodeList nodeList = xmlDoc.SelectSingleNode("Tree").ChildNodes;
foreach (XmlNode xn in nodeList)
{
XmlElement xe = (XmlElement)xn;
if (xe.Name == "Node")
{
XmlNodeList nls = xe.ChildNodes;
foreach (XmlNode xn1 in nls)
{
XmlElement xe2 = (XmlElement)xn1;
if (xe2.Name == "PageId" && xe2.InnerText == nodeID)
{
XmlNode xnChild = (XmlNode)xe2;
XmlNode child = xnChild.ParentNode.ChildNodes[NodeNum + 1];
XmlElement xeChild = (XmlElement)child;
string Id = xeChild.GetAttribute("value");
int Pid = int.Parse(Id);
res.msgPage = child.InnerText.ToString();
res.msgPrompt = xnChild.ParentNode.ChildNodes[NodeNum + 2].InnerText.ToString();
res.size = Pid;
return res;
}
break;
}
}
}
}
catch { }
return null;
}
}
邏輯流程分析
- 從
AppSettings 讀取基礎路徑,拼接檔案名
- 載入 XML,取得
<Tree> 直系子節點
- 遍歷每個
<Node>,尋找 <PageId> 匹配
- 匹配成功後,透過固定索引取得同層級後續節點(
Control、Message)
- 解析屬性與內容填充結構體
關鍵缺陷與風險
| 問題 | 影響 | 修正建議 |
硬編碼索引 NodeNum+1 | XML 節點順序變更即失效 | 使用 XPath Control/Message 直接選擇 |
catch { } 吞沒異常 | 檔案不存在、格式錯誤無感知 | 記錄日誌、拋出自訂異常或回傳 Result 模式 |
靜態欄位 res | 執行緒不安全、狀態殘留 | 改為方法區域變數回傳 |
ConfigurationSettings 已過時 | .NET 2.0+ 建議 ConfigurationManager | 引用 System.Configuration 組件 |
| 無快取機制 | 每次請求重複 I/O 解析 | Application 級快取或 MemoryCache |
重構版本草案
public sealed class InputLengthResolver
{
private readonly Dictionary _cache = new();
private readonly string _xmlPath;
public InputLengthResolver(string xmlPath) => _xmlPath = xmlPath;
public InputRule Resolve(string controlId)
{
if (_cache.TryGetValue(controlId, out var rule)) return rule;
var doc = XDocument.Load(_xmlPath);
var element = doc.XPathSelectElement($"/Tree/Node[PageId='{controlId}']");
if (element == null) return InputRule.Default;
rule = new InputRule
{
MaxLength = (int)element.Element("Control").Attribute("value"),
PageMessage = (string)element.Element("Message"),
PromptMessage = (string)element.Element("Prompt") // 假設新增
};
_cache[controlId] = rule;
return rule;
}
}
public struct InputRule
{
public int MaxLength;
public string PageMessage;
public string PromptMessage;
public static InputRule Default => new InputRule { MaxLength = int.MaxValue };
}