Откопал еще один свой раритет. Класс для форматирования отладочных сообщений. Сейчас, когда уже полно всяких отладочных фреймвоков, его полезность сомнительна, а на момент его написания (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)); }
}
}
Комментариев нет:
Отправить комментарий