Merge remote-tracking branch 'origin/6.2.0' into 6.2.0-membershipprovider
This commit is contained in:
@@ -22,8 +22,8 @@ namespace Umbraco.Core
|
||||
if (value is string)
|
||||
{
|
||||
var str = (string)value;
|
||||
if (str == null || str.Length == 0 || str == "0") return false;
|
||||
if (str == "1") return true;
|
||||
if (str == "0" || str == "") return false;
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace Umbraco.Core
|
||||
{
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
|
||||
//private static readonly ConcurrentDictionary<Type, Func<object>> ObjectFactoryCache = new ConcurrentDictionary<Type, Func<object>>();
|
||||
|
||||
public static IEnumerable<T> AsEnumerableOfOne<T>(this T input)
|
||||
@@ -86,8 +85,30 @@ namespace Umbraco.Core
|
||||
//check for string so that overloaders of ToString() can take advantage of the conversion.
|
||||
if (destinationType == typeof(string)) return Attempt<object>.Succeed(input.ToString());
|
||||
|
||||
if (!destinationType.IsGenericType || destinationType.GetGenericTypeDefinition() != typeof(Nullable<>))
|
||||
// if we've got a nullable of something, we try to convert directly to that thing.
|
||||
if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
// recursively call into myself with the inner (not-nullable) type and handle the outcome
|
||||
var nonNullable = input.TryConvertTo(Nullable.GetUnderlyingType(destinationType));
|
||||
|
||||
// and if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception
|
||||
if (nonNullable.Success)
|
||||
input = nonNullable.Result; // now fall on through...
|
||||
else
|
||||
return Attempt<object>.Fail(nonNullable.Exception);
|
||||
}
|
||||
|
||||
// we've already dealed with nullables, so any other generic types need to fall through
|
||||
if (!destinationType.IsGenericType)
|
||||
{
|
||||
if (input is string)
|
||||
{
|
||||
var result = TryConvertToFromString(input as string, destinationType);
|
||||
|
||||
// if we processed the string (succeed or fail), we're done
|
||||
if (result.HasValue) return result.Value;
|
||||
}
|
||||
|
||||
//TODO: Do a check for destination type being IEnumerable<T> and source type implementing IEnumerable<T> with
|
||||
// the same 'T', then we'd have to find the extension method for the type AsEnumerable() and execute it.
|
||||
|
||||
@@ -151,7 +172,6 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<IConvertible>(input))
|
||||
{
|
||||
try
|
||||
@@ -168,6 +188,119 @@ namespace Umbraco.Core
|
||||
return Attempt<object>.Fail();
|
||||
}
|
||||
|
||||
private static Nullable<Attempt<object>> TryConvertToFromString(this string input, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
return Attempt<object>.Succeed(input);
|
||||
|
||||
if (input == null || input.Length == 0)
|
||||
{
|
||||
if (destinationType == typeof(Boolean))
|
||||
return Attempt<object>.Succeed(false); // special case for booleans, null/empty == false
|
||||
else if (destinationType == typeof(DateTime))
|
||||
return Attempt<object>.Succeed(DateTime.MinValue);
|
||||
}
|
||||
|
||||
// we have a non-empty string, look for type conversions in the expected order of frequency of use...
|
||||
if (destinationType.IsPrimitive)
|
||||
{
|
||||
if (destinationType == typeof(Int32))
|
||||
{
|
||||
Int32 value;
|
||||
return Int32.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Int64))
|
||||
{
|
||||
Int64 value;
|
||||
return Int64.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Boolean))
|
||||
{
|
||||
Boolean value;
|
||||
if (Boolean.TryParse(input, out value))
|
||||
return Attempt<object>.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try
|
||||
}
|
||||
else if (destinationType == typeof(Int16))
|
||||
{
|
||||
Int16 value;
|
||||
return Int16.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Double))
|
||||
{
|
||||
Double value;
|
||||
return Double.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Single))
|
||||
{
|
||||
Single value;
|
||||
return Single.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Char))
|
||||
{
|
||||
Char value;
|
||||
return Char.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Byte))
|
||||
{
|
||||
Byte value;
|
||||
return Byte.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(SByte))
|
||||
{
|
||||
SByte value;
|
||||
return SByte.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(UInt32))
|
||||
{
|
||||
UInt32 value;
|
||||
return UInt32.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(UInt16))
|
||||
{
|
||||
UInt16 value;
|
||||
return UInt16.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(UInt64))
|
||||
{
|
||||
UInt64 value;
|
||||
return UInt64.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
}
|
||||
else if (destinationType == typeof(Guid))
|
||||
{
|
||||
Guid value;
|
||||
return Guid.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(DateTime))
|
||||
{
|
||||
DateTime value;
|
||||
return DateTime.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(DateTimeOffset))
|
||||
{
|
||||
DateTimeOffset value;
|
||||
return DateTimeOffset.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(TimeSpan))
|
||||
{
|
||||
TimeSpan value;
|
||||
return TimeSpan.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Decimal))
|
||||
{
|
||||
Decimal value;
|
||||
return Decimal.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
else if (destinationType == typeof(Version))
|
||||
{
|
||||
Version value;
|
||||
return Version.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
|
||||
}
|
||||
// E_NOTIMPL IPAddress, BigInteger
|
||||
|
||||
return null; // we can't decide...
|
||||
}
|
||||
|
||||
internal static void CheckThrowObjectDisposed(this IDisposable disposable, bool isDisposed, string objectname)
|
||||
{
|
||||
//TODO: Localise this exception
|
||||
@@ -289,7 +422,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
return "\"{0}\"".InvariantFormat(obj);
|
||||
}
|
||||
if (obj is int || obj is Int16 || obj is Int64 || obj is double || obj is bool || obj is int? || obj is Int16? || obj is Int64? || obj is double? || obj is bool?)
|
||||
if (obj is int || obj is Int16 || obj is Int64 || obj is float || obj is double || obj is bool || obj is int? || obj is Int16? || obj is Int64? || obj is float? || obj is double? || obj is bool?)
|
||||
{
|
||||
return "{0}".InvariantFormat(obj);
|
||||
}
|
||||
@@ -416,6 +549,5 @@ namespace Umbraco.Core
|
||||
return "[GetPropertyValueException]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.PartialTrust;
|
||||
@@ -83,8 +85,8 @@ namespace Umbraco.Tests
|
||||
{
|
||||
var result = testCase.Key.TryConvertTo<bool>();
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(testCase.Value, result.Result);
|
||||
Assert.IsTrue(result.Success, testCase.Key);
|
||||
Assert.AreEqual(testCase.Value, result.Result, testCase.Key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,39 +98,50 @@ namespace Umbraco.Tests
|
||||
{
|
||||
{"2012-11-10", true},
|
||||
{"2012/11/10", true},
|
||||
{"10/11/2012", true},
|
||||
{"11/10/2012", false},
|
||||
{"10/11/2012", true}, // assuming your culture uses DD/MM/YYYY
|
||||
{"11/10/2012", false}, // assuming your culture uses DD/MM/YYYY
|
||||
{"Sat 10, Nov 2012", true},
|
||||
{"Saturday 10, Nov 2012", true},
|
||||
{"Sat 10, November 2012", true},
|
||||
{"Saturday 10, November 2012", true},
|
||||
{"2012-11-10 13:14:15", true},
|
||||
{"", false}
|
||||
{"2012-11-10 13:14:15", true}
|
||||
};
|
||||
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var result = testCase.Key.TryConvertTo<DateTime>();
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value);
|
||||
Assert.IsTrue(result.Success, testCase.Key);
|
||||
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value, testCase.Key);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public virtual void CanConvertObjectToString_Using_ToString_Overload()
|
||||
{
|
||||
var result = new MyTestObject().TryConvertTo<string>();
|
||||
[Test]
|
||||
public virtual void CanConvertBlankStringToDateTime()
|
||||
{
|
||||
var result = "".TryConvertTo<DateTime>();
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(DateTime.MinValue, result.Result);
|
||||
}
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual("Hello world", result.Result);
|
||||
}
|
||||
[Test]
|
||||
public virtual void CanConvertObjectToString_Using_ToString_Overload()
|
||||
{
|
||||
var result = new MyTestObject().TryConvertTo<string>();
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual("Hello world", result.Result);
|
||||
}
|
||||
|
||||
private CultureInfo savedCulture;
|
||||
|
||||
/// <summary>
|
||||
/// Run once before each test in derived test fixtures.
|
||||
/// </summary>
|
||||
public override void TestSetup()
|
||||
{
|
||||
savedCulture = Thread.CurrentThread.CurrentCulture;
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); // make sure the dates parse correctly
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,6 +150,7 @@ namespace Umbraco.Tests
|
||||
/// </summary>
|
||||
public override void TestTearDown()
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = savedCulture;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user