Browse Source

Merge pull request #3942 from markl65536/FixTypeUtilities

Fix type utilities
pull/3877/head
Steven Kirk 6 years ago
committed by GitHub
parent
commit
17a44015c6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      src/Avalonia.Base/Utilities/TypeUtilities.cs
  2. 88
      tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs

43
src/Avalonia.Base/Utilities/TypeUtilities.cs

@ -115,45 +115,46 @@ namespace Avalonia.Utilities
return true;
}
var toUnderl = Nullable.GetUnderlyingType(to) ?? to;
var from = value.GetType();
if (to.IsAssignableFrom(from))
if (toUnderl.IsAssignableFrom(from))
{
result = value;
return true;
}
if (to == typeof(string))
if (toUnderl == typeof(string))
{
result = Convert.ToString(value);
result = Convert.ToString(value, culture);
return true;
}
if (to.IsEnum && from == typeof(string))
if (toUnderl.IsEnum && from == typeof(string))
{
if (Enum.IsDefined(to, (string)value))
if (Enum.IsDefined(toUnderl, (string)value))
{
result = Enum.Parse(to, (string)value);
result = Enum.Parse(toUnderl, (string)value);
return true;
}
}
if (!from.IsEnum && to.IsEnum)
if (!from.IsEnum && toUnderl.IsEnum)
{
result = null;
if (TryConvert(Enum.GetUnderlyingType(to), value, culture, out object enumValue))
if (TryConvert(Enum.GetUnderlyingType(toUnderl), value, culture, out object enumValue))
{
result = Enum.ToObject(to, enumValue);
result = Enum.ToObject(toUnderl, enumValue);
return true;
}
}
if (from.IsEnum && IsNumeric(to))
if (from.IsEnum && IsNumeric(toUnderl))
{
try
{
result = Convert.ChangeType((int)value, to, culture);
result = Convert.ChangeType((int)value, toUnderl, culture);
return true;
}
catch
@ -164,7 +165,7 @@ namespace Avalonia.Utilities
}
var convertableFrom = Array.IndexOf(InbuiltTypes, from);
var convertableTo = Array.IndexOf(InbuiltTypes, to);
var convertableTo = Array.IndexOf(InbuiltTypes, toUnderl);
if (convertableFrom != -1 && convertableTo != -1)
{
@ -172,7 +173,7 @@ namespace Avalonia.Utilities
{
try
{
result = Convert.ChangeType(value, to, culture);
result = Convert.ChangeType(value, toUnderl, culture);
return true;
}
catch
@ -183,15 +184,23 @@ namespace Avalonia.Utilities
}
}
var typeConverter = TypeDescriptor.GetConverter(to);
var toTypeConverter = TypeDescriptor.GetConverter(toUnderl);
if (toTypeConverter.CanConvertFrom(from) == true)
{
result = toTypeConverter.ConvertFrom(null, culture, value);
return true;
}
var fromTypeConverter = TypeDescriptor.GetConverter(from);
if (typeConverter.CanConvertFrom(from) == true)
if (fromTypeConverter.CanConvertTo(toUnderl) == true)
{
result = typeConverter.ConvertFrom(null, culture, value);
result = fromTypeConverter.ConvertTo(null, culture, value, toUnderl);
return true;
}
var cast = FindTypeConversionOperatorMethod(from, to, OperatorType.Implicit | OperatorType.Explicit);
var cast = FindTypeConversionOperatorMethod(from, toUnderl, OperatorType.Implicit | OperatorType.Explicit);
if (cast != null)
{

88
tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs

@ -6,6 +6,7 @@ using System.Windows.Input;
using System;
using Avalonia.Data.Converters;
using Avalonia.Layout;
using System.ComponentModel;
namespace Avalonia.Base.UnitTests.Data.Converters
{
@ -35,6 +36,54 @@ namespace Avalonia.Base.UnitTests.Data.Converters
Assert.Equal(5.0, result);
}
[Fact]
public void Do_Not_Throw_On_InvalidInput_For_NullableInt()
{
var result = DefaultValueConverter.Instance.Convert(
"<not-a-number>",
typeof(int?),
null,
CultureInfo.InvariantCulture);
Assert.IsType(typeof(BindingNotification), result);
}
[Fact]
public void Can_Convert_Decimal_To_NullableDouble()
{
var result = DefaultValueConverter.Instance.Convert(
5m,
typeof(double?),
null,
CultureInfo.InvariantCulture);
Assert.Equal(5.0, result);
}
[Fact]
public void Can_Convert_CustomType_To_Int()
{
var result = DefaultValueConverter.Instance.Convert(
new CustomType(123),
typeof(int),
null,
CultureInfo.InvariantCulture);
Assert.Equal(123, result);
}
[Fact]
public void Can_Convert_Int_To_CustomType()
{
var result = DefaultValueConverter.Instance.Convert(
123,
typeof(CustomType),
null,
CultureInfo.InvariantCulture);
Assert.Equal(new CustomType(123), result);
}
[Fact]
public void Can_Convert_String_To_Enum()
{
@ -187,5 +236,44 @@ namespace Avalonia.Base.UnitTests.Data.Converters
return v.Value;
}
}
[TypeConverter(typeof(CustomTypeConverter))]
private class CustomType {
public int Value { get; }
public CustomType(int value)
{
Value = value;
}
public override bool Equals(object obj)
{
return obj is CustomType other && this.Value == other.Value;
}
}
private class CustomTypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(int);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(int);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return ((CustomType)value).Value;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return new CustomType((int)value);
}
}
}
}

Loading…
Cancel
Save