Browse Source

Merge pull request #251 from Squidex/orleans-preparation

Mapper improved to get rid of exceptions.
pull/252/head
Sebastian Stehle 8 years ago
committed by GitHub
parent
commit
d0e725f1ae
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      src/Squidex.Infrastructure/Reflection/SimpleMapper.cs
  2. 153
      tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs

37
src/Squidex.Infrastructure/Reflection/SimpleMapper.cs

@ -16,6 +16,23 @@ namespace Squidex.Infrastructure.Reflection
{
public static class SimpleMapper
{
private sealed class StringConversionPropertyMapper : PropertyMapper
{
public StringConversionPropertyMapper(
IPropertyAccessor sourceAccessor,
IPropertyAccessor targetAccessor)
: base(sourceAccessor, targetAccessor)
{
}
public override void MapProperty(object source, object target, CultureInfo culture)
{
var value = GetValue(source);
SetValue(target, value?.ToString());
}
}
private sealed class ConversionPropertyMapper : PropertyMapper
{
private readonly Type targetType;
@ -38,21 +55,15 @@ namespace Squidex.Infrastructure.Reflection
return;
}
object converted;
try
{
converted = Convert.ChangeType(value, targetType, culture);
var converted = Convert.ChangeType(value, targetType, culture);
SetValue(target, converted);
}
catch (InvalidCastException)
catch
{
if (targetType == typeof(string))
{
converted = value.ToString();
SetValue(target, converted);
}
return;
}
}
}
@ -120,7 +131,13 @@ namespace Squidex.Infrastructure.Reflection
new PropertyAccessor(sourceClassType, sourceProperty),
new PropertyAccessor(targetClassType, targetProperty)));
}
else if (targetType.Implements<IConvertible>())
else if (targetType == typeof(string))
{
Mappers.Add(new StringConversionPropertyMapper(
new PropertyAccessor(sourceClassType, sourceProperty),
new PropertyAccessor(targetClassType, targetProperty)));
}
else if (sourceType.Implements<IConvertible>())
{
Mappers.Add(new ConversionPropertyMapper(
new PropertyAccessor(sourceClassType, sourceProperty),

153
tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs

@ -6,111 +6,158 @@
// ==========================================================================
using System;
using NodaTime;
using System.Diagnostics;
using Xunit;
namespace Squidex.Infrastructure.Reflection
{
public class SimpleMapperTests
{
public class MyClass1Base
public class Class1Base<T1>
{
public Guid MappedGuid { get; set; }
public string MappedString { get; set; }
public T1 P1 { get; set; }
}
public string MappedNull { get; set; }
public class Class1<T1, T2> : Class1Base<T1>
{
public T2 P2 { get; set; }
}
public long MappedNumber { get; set; }
public class Class2Base<T2>
{
public T2 P2 { get; set; }
}
public long WrongType1 { get; set; }
public class Class2<T2, T3> : Class2Base<T2>
{
public T3 P3 { get; set; }
}
public long WrongType2 { get; set; }
public class Readonly<T>
{
public T P1 { get; }
}
public class MyClass1 : MyClass1Base
public class Writeonly<T>
{
public string UnmappedString { get; set; }
public T P1
{
set { Debug.WriteLine(value); }
}
}
public class MyClass2Base
[Fact]
public void Should_throw_exception_if_mapping_with_null_source()
{
public string MappedString { get; protected set; }
Assert.Throws<ArgumentNullException>(() => SimpleMapper.Map((Class2<int, int>)null, new Class2<int, int>()));
}
public int MappedNull { get; set; }
[Fact]
public void Should_throw_exception_if_mapping_with_null_target()
{
Assert.Throws<ArgumentNullException>(() => SimpleMapper.Map(new Class2<int, int>(), (Class2<int, int>)null));
}
public int MappedNumber { get; set; }
[Fact]
public void Should_map_to_same_type()
{
var obj1 = new Class1<int, int>
{
P1 = 6,
P2 = 8
};
var obj2 = SimpleMapper.Map(obj1, new Class2<int, int>());
public string MappedGuid { get; set; }
Assert.Equal(8, obj2.P2);
Assert.Equal(0, obj2.P3);
}
public class MyClass2 : MyClass2Base
[Fact]
public void Should_map_all_properties()
{
public string UnmappedString
var obj1 = new Class1<int, int>
{
get { return "Value"; }
}
public Instant WrongType1 { get; set; }
P1 = 6,
P2 = 8
};
var obj2 = SimpleMapper.Map(obj1, new Class1<int, int>());
public Duration WrongType2 { get; set; }
Assert.Equal(6, obj2.P1);
Assert.Equal(8, obj2.P2);
}
[Fact]
public void Should_throw_exception_if_mapping_with_null_source()
public void Should_map_to_convertible_type()
{
Assert.Throws<ArgumentNullException>(() => SimpleMapper.Map((MyClass1)null, new MyClass2()));
var obj1 = new Class1<long, long>
{
P1 = 6,
P2 = 8
};
var obj2 = SimpleMapper.Map(obj1, new Class2<int, int>());
Assert.Equal(8, obj2.P2);
Assert.Equal(0, obj2.P3);
}
[Fact]
public void Should_throw_exception_if_mapping_with_null_target()
public void Should_map_when_convertible_is_null()
{
Assert.Throws<ArgumentNullException>(() => SimpleMapper.Map(new MyClass1(), (MyClass2)null));
var obj1 = new Class1<int?, int?>
{
P1 = null,
P2 = null
};
var obj2 = SimpleMapper.Map(obj1, new Class1<int, int>());
Assert.Equal(0, obj2.P1);
Assert.Equal(0, obj2.P2);
}
[Fact]
public void Should_map_to_type()
public void Should_convert_to_string()
{
var class1 = new MyClass1
var obj1 = new Class1<RefToken, RefToken>
{
UnmappedString = Guid.NewGuid().ToString(),
MappedString = Guid.NewGuid().ToString(),
MappedNumber = 123,
MappedGuid = Guid.NewGuid()
P1 = new RefToken("user", "1"),
P2 = new RefToken("user", "2")
};
var obj2 = SimpleMapper.Map(obj1, new Class2<string, string>());
var class2 = SimpleMapper.Map<MyClass1, MyClass2>(class1);
AssertObjectEquality(class1, class2);
Assert.Equal("user:2", obj2.P2);
Assert.Null(obj2.P3);
}
[Fact]
public void Should_map_between_types()
public void Should_return_default_if_conversion_failed()
{
var class1 = new MyClass1
var obj1 = new Class1<long, long>
{
UnmappedString = Guid.NewGuid().ToString(),
MappedString = Guid.NewGuid().ToString(),
MappedNumber = 123,
MappedGuid = Guid.NewGuid()
P1 = long.MaxValue,
P2 = long.MaxValue
};
var class2 = new MyClass2();
SimpleMapper.Map(class1, class2);
var obj2 = SimpleMapper.Map(obj1, new Class2<int, int>());
AssertObjectEquality(class1, class2);
Assert.Equal(0, obj2.P2);
Assert.Equal(0, obj2.P3);
}
private static void AssertObjectEquality(MyClass1 class1, MyClass2 class2)
[Fact]
public void Should_ignore_write_only()
{
Assert.Equal(class1.MappedString, class2.MappedString);
Assert.Equal(class1.MappedNumber, class2.MappedNumber);
Assert.Equal(class1.MappedGuid.ToString(), class2.MappedGuid);
var obj1 = new Writeonly<int>();
var obj2 = SimpleMapper.Map(obj1, new Class1<int, int>());
Assert.Equal(0, obj2.P1);
}
Assert.NotEqual(class1.UnmappedString, class2.UnmappedString);
[Fact]
public void Should_ignore_read_only()
{
var obj1 = new Class1<int, int> { P1 = 10 };
var obj2 = SimpleMapper.Map(obj1, new Readonly<int>());
Assert.Equal(0L, class1.WrongType1);
Assert.Equal(0L, class1.WrongType2);
Assert.Equal(0, obj2.P1);
}
}
}

Loading…
Cancel
Save