Parser.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. namespace CommonLang
  6. {
  7. public static class Parser
  8. {
  9. private static HashMap<Type, ParserAdapter> mParsers = new HashMap<Type, ParserAdapter>();
  10. private static string FloatFormat = "F";
  11. static Parser()
  12. {
  13. RegistParser(new ListParser<sbyte>());
  14. RegistParser(new ListParser<byte>());
  15. RegistParser(new ListParser<short>());
  16. RegistParser(new ListParser<ushort>());
  17. RegistParser(new ListParser<int>());
  18. RegistParser(new ListParser<uint>());
  19. RegistParser(new ListParser<long>());
  20. RegistParser(new ListParser<ulong>());
  21. RegistParser(new ListParser<float>());
  22. RegistParser(new ListParser<double>());
  23. RegistParser(new ListParser<decimal>());
  24. RegistParser(new ListParser<char>());
  25. RegistParser(new ListParser<bool>());
  26. RegistParser(new ListParser<string>());
  27. RegistParser(new ListParser<object>());
  28. }
  29. public static void RegistParser(ParserAdapter parser)
  30. {
  31. mParsers.Put(parser.ParserType, parser);
  32. }
  33. public static void SetFloatFormat(string format)
  34. {
  35. FloatFormat = format;
  36. }
  37. public static bool TryConvertTo(object src, Type targetType)
  38. {
  39. object target;
  40. return TryConvertTo(src, targetType, out target);
  41. }
  42. public static bool TryConvertTo(object src, Type targetType, out object target)
  43. {
  44. if (targetType.IsInstanceOfType(src))
  45. {
  46. target = src;
  47. return true;
  48. }
  49. if (targetType.IsPrimitive && src.GetType().IsPrimitive)
  50. {
  51. try
  52. {
  53. target = Convert.ChangeType(src, targetType);
  54. if (targetType.IsInstanceOfType(target))
  55. {
  56. return true;
  57. }
  58. }
  59. catch (Exception err)
  60. {
  61. Console.WriteLine("TryConvertTo : " + src + " -> " + targetType + ", catch: " + err);
  62. }
  63. }
  64. target = null;
  65. return false;
  66. }
  67. public static bool StringToObject<T>(string text, out T ret)
  68. {
  69. Type type = typeof(T);
  70. try
  71. {
  72. ret = (T)StringToObject(text, type);
  73. return true;
  74. }
  75. catch (Exception err)
  76. {
  77. Console.WriteLine("StringToObject 1: " + text + ", catch: " + err);
  78. ret = default(T);
  79. return false;
  80. }
  81. }
  82. public static object StringToObject(string text, Type type)
  83. {
  84. if (String.IsNullOrEmpty(text))
  85. {
  86. return null;
  87. }
  88. ParserAdapter parser = mParsers.Get(type);
  89. if (parser != null)
  90. {
  91. object ret = parser.StringToObject(text);
  92. if (ret != null)
  93. {
  94. return ret;
  95. }
  96. }
  97. if (type.IsArray)
  98. {
  99. int rank = type.GetArrayRank();
  100. if (rank == 1)
  101. {
  102. Type subtype = type.GetElementType();
  103. string[] kvs = text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  104. Array array = Array.CreateInstance(subtype, kvs.Length);
  105. for (int i = 0; i < kvs.Length; i++)
  106. {
  107. object obj = StringToObject(kvs[i], subtype);
  108. array.SetValue(obj, i);
  109. }
  110. return array;
  111. }
  112. else if (rank == 2)
  113. {
  114. int a0 = text.IndexOf('{');
  115. int a1 = text.LastIndexOf('}');
  116. if (a0 >= 0 && a1 > a0)
  117. {
  118. Type subtype = type.GetElementType();
  119. Array array = null;
  120. string stext = text.Substring(a0 + 1, a1 - a0 - 1);
  121. string[] range0 = Regex.Split(stext, @"\}\s*,\s*\{");
  122. for (int i = 0; i < range0.Length; i++)
  123. {
  124. string[] range1 = range0[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  125. if (array == null)
  126. {
  127. array = Array.CreateInstance(subtype, range0.Length, range1.Length);
  128. }
  129. for (int j = 0; j < range1.Length; j++)
  130. {
  131. object obj = StringToObject(range1[j], subtype);
  132. array.SetValue(obj, i, j);
  133. }
  134. }
  135. return array;
  136. }
  137. }
  138. }
  139. if (type.IsEnum)
  140. {
  141. try
  142. {
  143. return Enum.Parse(type, text, true);
  144. }
  145. catch (Exception err)
  146. {
  147. Console.WriteLine("StringToObject2 : " + text + ", catch: " + err);
  148. return null;
  149. }
  150. }
  151. if (type.IsAssignableFrom(typeof(string)))
  152. {
  153. return text;
  154. }
  155. if (type.IsAssignableFrom(typeof(int)))
  156. {
  157. return int.Parse(text);
  158. }
  159. if (type.IsAssignableFrom(typeof(uint)))
  160. {
  161. return uint.Parse(text);
  162. }
  163. if (type.IsAssignableFrom(typeof(short)))
  164. {
  165. return short.Parse(text);
  166. }
  167. if (type.IsAssignableFrom(typeof(ushort)))
  168. {
  169. return ushort.Parse(text);
  170. }
  171. if (type.IsAssignableFrom(typeof(byte)))
  172. {
  173. return byte.Parse(text);
  174. }
  175. if (type.IsAssignableFrom(typeof(sbyte)))
  176. {
  177. return sbyte.Parse(text);
  178. }
  179. if (type.IsAssignableFrom(typeof(bool)))
  180. {
  181. return bool.Parse(text);
  182. }
  183. if (type.IsAssignableFrom(typeof(float)))
  184. {
  185. if (text == float.NaN.ToString())
  186. {
  187. return float.NaN;
  188. }
  189. return float.Parse(text, System.Globalization.CultureInfo.InvariantCulture);
  190. }
  191. if (type.IsAssignableFrom(typeof(double)))
  192. {
  193. return float.Parse(text, System.Globalization.CultureInfo.InvariantCulture);
  194. }
  195. return null;
  196. }
  197. public static string ObjectToString(object obj)
  198. {
  199. if (obj == null)
  200. {
  201. return "";
  202. }
  203. Type type = obj.GetType();
  204. ParserAdapter parser = mParsers.Get(type);
  205. if (parser != null)
  206. {
  207. string ret = parser.ObjectToString(obj);
  208. if (ret != null)
  209. {
  210. return ret;
  211. }
  212. }
  213. if (type.IsArray)
  214. {
  215. int rank = type.GetArrayRank();
  216. if (rank == 1)
  217. {
  218. Array array = (Array)obj;
  219. StringBuilder sb = new StringBuilder();
  220. Type subtype = type.GetElementType();
  221. for (int i = 0; i < array.Length; i++)
  222. {
  223. sb.Append(ObjectToString(array.GetValue(i)));
  224. if (i < array.Length - 1)
  225. {
  226. sb.Append(",");
  227. }
  228. }
  229. return sb.ToString();
  230. }
  231. else if (rank == 2)
  232. {
  233. Array array = (Array)obj;
  234. StringBuilder sb = new StringBuilder();
  235. for (int i = 0; i < array.GetLength(0); i++)
  236. {
  237. sb.Append("{");
  238. for (int j = 0; j < array.GetLength(1); j++)
  239. {
  240. sb.Append(ObjectToString(array.GetValue(i, j)));
  241. if (j < array.GetLength(1) - 1)
  242. {
  243. sb.Append(",");
  244. }
  245. }
  246. sb.Append("}");
  247. if (i < array.GetLength(0) - 1)
  248. {
  249. sb.Append(",");
  250. }
  251. }
  252. return sb.ToString();
  253. }
  254. }
  255. if (type.IsEnum)
  256. {
  257. return Enum.GetName(type, obj);
  258. }
  259. if (obj is float)
  260. {
  261. return ((float)obj).ToString(FloatFormat);
  262. }
  263. if (obj is double)
  264. {
  265. return ((double)obj).ToString(FloatFormat);
  266. }
  267. return obj + "";
  268. }
  269. public abstract class ParserAdapter
  270. {
  271. readonly public Type ParserType;
  272. public ParserAdapter(Type type)
  273. {
  274. this.ParserType = type;
  275. }
  276. public abstract object StringToObject(string text);
  277. public abstract string ObjectToString(object obj);
  278. }
  279. public class ListParser<T> : ParserAdapter
  280. {
  281. public ListParser()
  282. : base(typeof(List<T>))
  283. {
  284. }
  285. public override object StringToObject(string text)
  286. {
  287. string[] ss = text.Split(',');
  288. List<T> ret = null;
  289. if (ss.Length > 0)
  290. {
  291. ret = new List<T>();
  292. foreach (string s in ss)
  293. {
  294. T d = (T)Parser.StringToObject(s, typeof(T));
  295. ret.Add(d);
  296. }
  297. }
  298. return ret;
  299. }
  300. public override string ObjectToString(object obj)
  301. {
  302. List<T> list = (List<T>)obj;
  303. StringBuilder sb = new StringBuilder();
  304. int i = 0;
  305. foreach (T d in list)
  306. {
  307. sb.Append(ObjectToString(d));
  308. if (i < list.Count - 1)
  309. {
  310. sb.Append(",");
  311. }
  312. i++;
  313. }
  314. return sb.ToString();
  315. }
  316. }
  317. }
  318. }