Merge remote-tracking branch 'origin/6.2.0' into 6.2.0-membershipprovider

This commit is contained in:
Shannon
2013-10-18 16:14:24 +11:00
3 changed files with 167 additions and 21 deletions

View File

@@ -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);

View File

@@ -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]";
}
}
}
}

View File

@@ -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;
}