/* * Code from StackOverflow: http://stackoverflow.com/questions/1759154/c-string-parsing-to-variable-types * Author: http://stackoverflow.com/users/210809/ckknight */ using System; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading; namespace Core.Common.Utils { public static class StringExtensions { /// /// Replaces the first occurrence of in by /// /// The resulting string public static string ReplaceFirst(this string text, string oldValue, string newValue) { var pos = text.IndexOf(oldValue); return pos >= 0 ? text.Substring(0, pos) + newValue + text.Substring(pos + oldValue.Length) : text; } /// /// Parse the as a . If this cannot be achieved, return the default value of . /// /// The type to parse into. /// The string to parse. /// The resultant or the default of . /// /// /// "1234".Parse<int>() == 1234; /// "a".Parse<int>() == 0; /// "a".Parse<int?>() == null; /// "2010-01-01".Parse<DateTime?>() == new DateTime(2010, 1, 1) /// "2010-01-01a".Parse<DateTime?>() == null /// "127.0.0.1".Parse<System.Net.IPAddress>().Equals(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 })) /// "".Parse<System.Net.IPAddress>() == null /// /// public static T Parse(this string target) { return ParseHelper.Parse(target); } /// /// Parse the as a . If this cannot be achieved, return /// /// The type to parse into. /// The string to parse. /// The value to return if could not be parsed. /// The resultant or . /// /// /// "1234".Parse <int>(-1) == 1234; /// "a".Parse<int>(-1) == -1; /// "2010-01-01".Parse<DateTime?>(new DateTime(1900, 1, 1)) == new DateTime(2010, 1, 1) /// "2010-01-01a".Parse<DateTime?>(new DateTime(1900, 1, 1)) == new DateTime(1900, 1, 1) /// "127.0.0.1".Parse<System.Net.IPAddress>(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 })).Equals(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 })) /// "".Parse<System.Net.IPAddress>(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 })).Equals(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 })) /// /// public static T Parse(this string target, T defaultValue) { return ParseHelper.Parse(target, defaultValue); } public static T Parse(this string target, CultureInfo culture) { var culture1 = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var result = ParseHelper.Parse(target); Thread.CurrentThread.CurrentCulture = culture1; return result; } private static class ParseHelper { private static readonly Func _parser; static ParseHelper() { Type type = typeof(T); bool isNullable = false; if (type.GetGenericArguments().Length > 0 && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { isNullable = true; type = type.GetGenericArguments()[0]; } ParameterExpression target = Expression.Parameter(typeof(string), "target"); ParameterExpression defaultValue = Expression.Parameter(typeof(T), "defaultValue"); ParameterExpression result = Expression.Parameter(typeof(T), "result"); Type helper = typeof(NullableParseHelper<>); if (isNullable) { helper = helper.MakeGenericType(typeof(T), type); MethodInfo parseMethod = helper.GetMethod("Parse"); _parser = Expression.Lambda>( Expression.Call(parseMethod, target, defaultValue), target, defaultValue, result).Compile(); } else { MethodInfo tryParseMethod = (from m in typeof(T).GetMethods() where m.Name == "TryParse" let ps = m.GetParameters() where ps.Count() == 2 && ps[0].ParameterType == typeof(string) && ps[1].ParameterType == typeof(T).MakeByRefType() select m).SingleOrDefault(); if (tryParseMethod == null) { throw new InvalidOperationException(String.Format("Cannot find method {0}.TryParse(string, out {0})", type.FullName)); } _parser = Expression.Lambda>( Expression.Condition( Expression.Call(tryParseMethod, target, result), result, defaultValue), target, defaultValue, result).Compile(); } } public static T Parse(string target) { return _parser.Invoke(target, default(T), default(T)); } public static T Parse(string target, T defaultValue) { return _parser.Invoke(target, defaultValue, default(T)); } private static class NullableParseHelper where TBase : struct { private static readonly Func _parser; static NullableParseHelper() { MethodInfo tryParseMethod = (from m in typeof(TBase).GetMethods() where m.Name == "TryParse" let ps = m.GetParameters() where ps.Count() == 2 && ps[0].ParameterType == typeof(string) && ps[1].ParameterType == typeof(TBase).MakeByRefType() select m).SingleOrDefault(); if (tryParseMethod == null) { throw new InvalidOperationException(String.Format("Cannot find method {0}.TryParse(string, out {0})", typeof(TBase).FullName)); } ParameterExpression target = Expression.Parameter(typeof(string), "target"); ParameterExpression defaultValue = Expression.Parameter(typeof(TBase?), "defaultValue"); ParameterExpression result = Expression.Parameter(typeof(TBase), "result"); _parser = Expression.Lambda>( Expression.Condition( Expression.Call(tryParseMethod, target, result), Expression.ConvertChecked(result, typeof(TBase?)), defaultValue), target, defaultValue, result).Compile(); } public static TBase? Parse(string target, TBase? defaultValue) { return _parser.Invoke(target, defaultValue, default(TBase)); } } } } }