Откопал еще один свой раритет. Класс для форматирования отладочных сообщений. Сейчас, когда уже полно всяких отладочных фреймвоков, его полезность сомнительна, а на момент его написания (2005 г.) была весьма полезная штука.
using System; using System.Reflection; using System.Text; using System.Data; using System.Data.SqlClient; ///TODO Защиту от циклических ссылок: сохранять ввыведенные объекты в хэштаблицу и не выводить второй раз через. ///Вместо этого ссылаться на первый вывод, для этого нужно сохранять полный путь выведенного объекта (напр. S.a[2].el) namespace Util { public class DebugPrint { // config public static int IndentSize = 4; public static bool ShowTypes = true; public static bool ShowArraysIndexes = false; public static BindingFlags BindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; // string functions public static string Indent(int i) { return "".PadLeft(i*IndentSize); } public static string Indent(string str) { string idt=Indent(1); str=idt+str; // indent first line str=str.Replace("\r\n","\r\n"+idt); // indent next lines if(str.EndsWith(idt)) str=LastReplace(str,idt,""); // unindent empty last line return str; } public static string LastRemove(string s, string last) { int i=s.LastIndexOf(last); return i<0?s:s.Remove(i,last.Length); } public static string LastRemove(string s, char last) { int i=s.LastIndexOf(last); return i<0?s:s.Remove(i,1); } public static string LastReplace(string s, string oldstr, string newstr) { int i=s.LastIndexOf(oldstr); return i<0?s:s.Remove(i,oldstr.Length).Insert(i,newstr); } public static string LastReplace(string s, char oldchar, string newstr) { int i=s.LastIndexOf(oldchar); return i<0?s:s.Remove(i,1).Insert(i,newstr); } // print functions protected static string PrintDimensions(Array arr) { string str="["; for(int i=0; i<arr.Rank; i++) str+=arr.GetLength(i).ToString()+","; return LastRemove(str,",")+"]"; } protected static string PrintIndexies(int[] idxs, int max) { string str = "["; for(int i=0; i<Math.Min(idxs.Length,max); i++) str+=idxs[i].ToString()+","; return LastRemove(str,",")+"]"; } protected static string PrintArray(string name, Array arr) { Type elementType = arr.GetType().GetElementType(); int[] arrIdx = new int[arr.Rank]; string str = ""; if(ShowTypes) str+=elementType.Name+PrintDimensions(arr)+" "; str+=name+" = \r\n"; str+=PrintDimension(name,arr,arrIdx,0); str=LastRemove(str,','); return str; } protected static string PrintDimension(string name, Array arr, int[] arrIdx, int dim) { string str = ""; Type elementType=arr.GetType().GetElementType(); for (int idx = arr.GetLowerBound(dim); idx <= arr.GetUpperBound(dim); idx++) { arrIdx[dim] = idx; if(dim<arr.Rank-1) str+=(ShowArraysIndexes?name+PrintIndexies(arrIdx,dim+1)+" = ":"")+PrintDimension(name,arr,arrIdx,dim+1); else if(elementType.IsPrimitive) str += arr.GetValue(arrIdx).ToString()+", "; else str += PrintObject((ShowArraysIndexes?name+PrintIndexies(arrIdx,dim+1):""), null, arr.GetValue(arrIdx)); } str=LastRemove(str,", "); if(dim==arr.Rank-1 && elementType.IsPrimitive) str="{"+str+"}, \r\n"; else str="{\r\n"+Indent(str)+"}, \r\n"; return str; } protected static string PrintStruct(string name, object obj) { Type type = obj.GetType(); string str = ""; FieldInfo[] fis = type.GetFields(BindingFlags); for(int i=0; i<fis.Length; i++) str += PrintObject(fis[i].Name, fis[i].FieldType, fis[i].GetValue(obj)); PropertyInfo[] pis = type.GetProperties(BindingFlags); if(pis.Length>0) str+="// Properties\r\n"; for(int i=0; i<pis.Length; i++) if(pis[i].GetGetMethod(true).GetParameters().Length>0) str+=pis[i].PropertyType.Name+" "+pis[i].Name+" = ?; // Can't print indexed properties\r\n"; else str += PrintObject(pis[i].Name, pis[i].PropertyType, pis[i].GetValue(obj,null)); return (name!=""?(ShowTypes?type.Name+" ":"")+name+" = \r\n":"")+"{\r\n"+Indent(str)+"}\r\n"; } public static string PrintObject(string name, Type type, object obj) { if(type==null && obj==null) return (name!=""?name+" = ":"")+"null;\r\n"; if(type==null) type = obj.GetType(); if(obj==null) return (name!=""?(ShowTypes?type.Name+" ":"")+name+" = ":"")+"null;\r\n"; if(type==typeof(String)) { return (ShowTypes?type.Name+" ":"")+name+" = \""+obj+"\";\r\n"; } else if(type.IsPrimitive || type.IsEnum) { return (ShowTypes?type.Name+" ":"")+name+" = "+obj.ToString()+";\r\n"; } else if (type.IsArray) { return PrintArray(name,(Array)obj); } else if (type.IsClass || type.IsValueType) { return PrintStruct(name,obj); } return "Unknow type of object"; } public static string PrintStream(System.IO.Stream m, bool hex) { string s=""; int len=(int)m.Length; byte[] buf = new byte[len]; m.Seek(0,System.IO.SeekOrigin.Begin); m.Read(buf,0,len); if(hex) for(int i=0; i<len; i++) s+=buf[i].ToString("X2")+" "; else s=System.Text.Encoding.UTF8.GetString(buf); return s; } public static string PrintDataReader(SqlDataReader r) { StringBuilder sb = new StringBuilder(); DataTable sch = r.GetSchemaTable(); for(int i=0; i<sch.Rows.Count; i++) sb.AppendFormat("{0,16}|",sch.Rows[i]["ColumnName"]); sb.Append("\r\n"); while(r.Read()) { for(int j=0; j<r.FieldCount; j++) sb.AppendFormat("{0,16}|",r[j]); sb.Append("\r\n"); } return sb.ToString(); } public static string PrintData(Sql sql, string query) { string ret = null; SqlDataReader r = sql.ExecuteReader(query); try { ret = PrintDataReader(r); } finally { r.Close(); } return ret; } // Wrappers public static string PrintObject(string name, object obj) { return PrintObject(name, null, obj); } public static string PrintObject(object obj) { return PrintObject("", null, obj); } public static string PrintStream(System.IO.Stream m) { return PrintStream(m, false); } public static string PrintData(Sql sql, string query, params object[] o) { return PrintData(sql, String.Format(query,o)); } } }
Комментариев нет:
Отправить комментарий