/*
* 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;
using Core.Common.Utils.Properties;
namespace Core.Common.Utils.Extensions
{
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 Enumerable.Count(ps) == 2
&& ps[0].ParameterType == typeof(string)
&& ps[1].ParameterType == typeof(T).MakeByRefType()
select m).SingleOrDefault();
if (tryParseMethod == null)
{
throw new InvalidOperationException(String.Format(Resource.ParseHelper_ParseHelper_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 Enumerable.Count(ps) == 2
&& ps[0].ParameterType == typeof(string)
&& ps[1].ParameterType == typeof(TBase).MakeByRefType()
select m).SingleOrDefault();
if (tryParseMethod == null)
{
throw new InvalidOperationException(String.Format(Resource.ParseHelper_ParseHelper_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));
}
}
}
}
}