C#可以通過反射讀取類的字段/方法等,可是該如何獲取該字段的XML注釋?
具體目的:有一個實體類,頁面需要有一個與其對應的table,樣式大體為
<tr> <td>地東經</td> <td> <input id='txt_Longitude' type='text' class='form-control' name='Longitude' /></td> <td>北緯</td> <td> <input id='Latitude' type='text' class='form-control' name='Latitude' /></td> </tr>
其實體類,大致為:
/// <summary> /// 東經 /// </summary> public double? Longitude { get{ return _Longitude; } set { this.OnPropertyValueChange(_.Longitude,_Longitude,value);
this._Longitude=value;
}
}
由於實體類中屬性很多,生成頁面的工作量很大,所以想通過反射的方式,讀取實體的XML注釋及其屬性名稱,寫個循環即可生成上述頁面
后查閱相關資料,XML注釋是不寫入DLL里的,所以直接通過反射的方式獲取XML注釋是不可能的.
有建議通過對XML文件進行解析,獲取其XML注釋的
萬能的老外已經處理過類似的問題了,參考這里
其提供了一個處理用的類庫以及示例
1.在VS里打開項目屬性中的XML文檔注釋功能
即在項目的bin目錄中生成一個以當前項目命名的xml文件,讀取該文件,即可獲取XML注釋
2.按照如下方式,獲取XML注釋
XmlElement documentation = DocsByReflection.XMLFromMember(typeof(SomeExampleClass).GetProperty("ExampleProperty"));
Console.WriteLine(documentation["summary"].InnerText.Trim());
下載鏈接:
通過反射獲取字段名稱/字段類型/及其XML注釋,即可根據需要生成頁面HTML,示例如下:
StringBuilder sb = new StringBuilder(); string rowtemp = "<tr>\r\n" + "<td>{0}</td>\r\n " + "<td>" + "<input id = 'txt_{1}' type = 'text' class='form-control' name='{1}' /></td>\r\n" + "<td>{2}</td>\r\n" + "<td>\r\n" + "<input id = '{3}' type='text' class='form-control' name='{3}' /></td>\r\n" + "</tr>\r\n"; //遍歷基本屬性,生成表 PropertyInfo[] ProList = tp1.GetProperties(); List<string> ignoreList = new List<string>(); ignoreList.Add("Project_Code"); bool toEnd = false; #region 區分字段類型 for (int i = 0; i < ProList.Length; ) {
//下述循環為了實現對字段的過濾,以及一行兩個<td>,所以,需要檢索出下一個可用的字段對象,看上去比較繞 while (ignoreList.Contains(ProList[i].Name)) { i++; if (i == ProList.Length) { toEnd = true; break; } } if (toEnd) { break; } PropertyInfo p1 = ProList[i]; i++; PropertyInfo p2 = null; if (i < ProList.Length) { while (ignoreList.Contains(ProList[i].Name)) { i++; if (i == ProList.Length) { toEnd = true; break; } } } if (toEnd || i == ProList.Length) { } else { p2 = ProList[i]; i++; } sb.AppendLine("<tr>"); if (p2 != null) { string str1 = getHTML(tp1, p1); string str2 = getHTML(tp1, p2); sb.AppendLine(str1); sb.AppendLine(str2); } else { string str1 = getHTML(tp1, p1); sb.AppendLine(str1); } sb.AppendLine("</tr>"); } #endregion write2Text(@"C:\STD\"+tp1.Name+".txt", sb); Console.WriteLine("結束"); Console.ReadLine();
public static string getCommentText(Type tp1,string nm) { Console.WriteLine(nm); XmlElement documentation = DocsByReflection.XMLFromMember(tp1.GetProperty(nm)); Console.WriteLine(documentation["summary"].InnerText.Trim()); return documentation["summary"].InnerText.Trim(); } public static void write2Text(string filename, StringBuilder sb) { using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate)) { using (StreamWriter sw = new StreamWriter(fs)) { sw.Write(sb.ToString()); sw.Flush(); } } } public static string getHTML(Type tp1,PropertyInfo p) { if (p.Name.Trim() == "Conveyance_Tunnel_Import_Elevation") Console.WriteLine(""); string inputTD = "<td>{0}</td>\r\n " + "<td>\r\n" + "<input id = 'txt_{1}' type = 'text' class='form-control' name='{1}' />\r\n"+ "</td>\r\n"; string selectTD = @"<td>{0}</td> <td> <select id='{1}' class='form-control' name='{1}'> {2} </select> </td>"; string chkTD = @"<td>{0}</td> <td> <label for='chkY_{1}'>是<input type='checkbox' id='chkY_{1}' value='true' class='form-control' name='{1}'></label> <label for='chkN_{1}'>否<input type='checkbox' value='false' id='chkN_{1}' class='form-control' name='{1}'></label> </td>"; if (p.PropertyType == typeof(Guid?)||p.PropertyType==typeof(Guid)) { //GUID類型的,去數據庫中查找並生成Select StringBuilder optSb = new StringBuilder(); DataTable dt = SqlHelper.ExecuteDataTable("select * from Foreign_Key_Table where Column_Code=@cc and Table_Code=@tc order by Order_ID", new SqlParameter("@cc", p.Name),new SqlParameter("tc",type_code)); if (dt.Rows.Count > 0) { for (int i = 0; i < dt.Rows.Count; i++) { optSb.AppendLine(string.Format("<option value='{0}'>{1}</option>", dt.Rows[i]["Key_Code"], dt.Rows[i]["Key_Name"])); } return string.Format(selectTD, getCommentText(tp1, p.Name), p.Name, optSb.ToString()); } else { //如果沒有查到,非外鍵表,直接顯示 return string.Format(inputTD, getCommentText(tp1, p.Name), p.Name); } } else if (p.PropertyType == typeof(bool?) || p.PropertyType == typeof(bool)) { return string.Format(chkTD,getCommentText(tp1, p.Name),p.Name); } else { //生成input return string.Format(inputTD,getCommentText(tp1,p.Name),p.Name); } }