using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; namespace CommonLang { public static class Parser { private static HashMap mParsers = new HashMap(); private static string FloatFormat = "F"; static Parser() { RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); RegistParser(new ListParser()); } public static void RegistParser(ParserAdapter parser) { mParsers.Put(parser.ParserType, parser); } public static void SetFloatFormat(string format) { FloatFormat = format; } public static bool TryConvertTo(object src, Type targetType) { object target; return TryConvertTo(src, targetType, out target); } public static bool TryConvertTo(object src, Type targetType, out object target) { if (targetType.IsInstanceOfType(src)) { target = src; return true; } if (targetType.IsPrimitive && src.GetType().IsPrimitive) { try { target = Convert.ChangeType(src, targetType); if (targetType.IsInstanceOfType(target)) { return true; } } catch (Exception err) { Console.WriteLine("TryConvertTo : " + src + " -> " + targetType + ", catch: " + err); } } target = null; return false; } public static bool StringToObject(string text, out T ret) { Type type = typeof(T); try { ret = (T)StringToObject(text, type); return true; } catch (Exception err) { Console.WriteLine("StringToObject 1: " + text + ", catch: " + err); ret = default(T); return false; } } public static object StringToObject(string text, Type type) { if (String.IsNullOrEmpty(text)) { return null; } ParserAdapter parser = mParsers.Get(type); if (parser != null) { object ret = parser.StringToObject(text); if (ret != null) { return ret; } } if (type.IsArray) { int rank = type.GetArrayRank(); if (rank == 1) { Type subtype = type.GetElementType(); string[] kvs = text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); Array array = Array.CreateInstance(subtype, kvs.Length); for (int i = 0; i < kvs.Length; i++) { object obj = StringToObject(kvs[i], subtype); array.SetValue(obj, i); } return array; } else if (rank == 2) { int a0 = text.IndexOf('{'); int a1 = text.LastIndexOf('}'); if (a0 >= 0 && a1 > a0) { Type subtype = type.GetElementType(); Array array = null; string stext = text.Substring(a0 + 1, a1 - a0 - 1); string[] range0 = Regex.Split(stext, @"\}\s*,\s*\{"); for (int i = 0; i < range0.Length; i++) { string[] range1 = range0[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (array == null) { array = Array.CreateInstance(subtype, range0.Length, range1.Length); } for (int j = 0; j < range1.Length; j++) { object obj = StringToObject(range1[j], subtype); array.SetValue(obj, i, j); } } return array; } } } if (type.IsEnum) { try { return Enum.Parse(type, text, true); } catch (Exception err) { Console.WriteLine("StringToObject2 : " + text + ", catch: " + err); return null; } } if (type.IsAssignableFrom(typeof(string))) { return text; } if (type.IsAssignableFrom(typeof(int))) { return int.Parse(text); } if (type.IsAssignableFrom(typeof(uint))) { return uint.Parse(text); } if (type.IsAssignableFrom(typeof(short))) { return short.Parse(text); } if (type.IsAssignableFrom(typeof(ushort))) { return ushort.Parse(text); } if (type.IsAssignableFrom(typeof(byte))) { return byte.Parse(text); } if (type.IsAssignableFrom(typeof(sbyte))) { return sbyte.Parse(text); } if (type.IsAssignableFrom(typeof(bool))) { return bool.Parse(text); } if (type.IsAssignableFrom(typeof(float))) { if (text == float.NaN.ToString()) { return float.NaN; } return float.Parse(text, System.Globalization.CultureInfo.InvariantCulture); } if (type.IsAssignableFrom(typeof(double))) { return float.Parse(text, System.Globalization.CultureInfo.InvariantCulture); } return null; } public static string ObjectToString(object obj) { if (obj == null) { return ""; } Type type = obj.GetType(); ParserAdapter parser = mParsers.Get(type); if (parser != null) { string ret = parser.ObjectToString(obj); if (ret != null) { return ret; } } if (type.IsArray) { int rank = type.GetArrayRank(); if (rank == 1) { Array array = (Array)obj; StringBuilder sb = new StringBuilder(); Type subtype = type.GetElementType(); for (int i = 0; i < array.Length; i++) { sb.Append(ObjectToString(array.GetValue(i))); if (i < array.Length - 1) { sb.Append(","); } } return sb.ToString(); } else if (rank == 2) { Array array = (Array)obj; StringBuilder sb = new StringBuilder(); for (int i = 0; i < array.GetLength(0); i++) { sb.Append("{"); for (int j = 0; j < array.GetLength(1); j++) { sb.Append(ObjectToString(array.GetValue(i, j))); if (j < array.GetLength(1) - 1) { sb.Append(","); } } sb.Append("}"); if (i < array.GetLength(0) - 1) { sb.Append(","); } } return sb.ToString(); } } if (type.IsEnum) { return Enum.GetName(type, obj); } if (obj is float) { return ((float)obj).ToString(FloatFormat); } if (obj is double) { return ((double)obj).ToString(FloatFormat); } return obj + ""; } public abstract class ParserAdapter { readonly public Type ParserType; public ParserAdapter(Type type) { this.ParserType = type; } public abstract object StringToObject(string text); public abstract string ObjectToString(object obj); } public class ListParser : ParserAdapter { public ListParser() : base(typeof(List)) { } public override object StringToObject(string text) { string[] ss = text.Split(','); List ret = null; if (ss.Length > 0) { ret = new List(); foreach (string s in ss) { T d = (T)Parser.StringToObject(s, typeof(T)); ret.Add(d); } } return ret; } public override string ObjectToString(object obj) { List list = (List)obj; StringBuilder sb = new StringBuilder(); int i = 0; foreach (T d in list) { sb.Append(ObjectToString(d)); if (i < list.Count - 1) { sb.Append(","); } i++; } return sb.ToString(); } } } }