Browse Source

Clear destination collection.

pull/17376/head
maliming 3 years ago
parent
commit
e70a0ac86a
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 16
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
  2. 79
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Specific_ObjectMapper_Tests.cs

16
framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs

@ -149,6 +149,12 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
? Activator.CreateInstance(definitionGenericType.MakeGenericType(destinationArgumentType))!.As<IList>()
: Array.CreateInstance(destinationArgumentType, sourceList.Count);
if (destination != null && !destination.GetType().IsArray)
{
//Clear destination collection if destination not an array, We won't change array just same behavior as AutoMapper.
destination.As<IList>().Clear();
}
for (var i = 0; i < sourceList.Count; i++)
{
var invokeResult = destination == null
@ -158,6 +164,7 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
if (definitionGenericType.IsGenericType)
{
result.Add(invokeResult);
destination?.As<IList>().Add(invokeResult);
}
else
{
@ -165,7 +172,14 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
}
}
return (TDestination)result!;
if (destination != null && destination.GetType().IsArray)
{
//Return the new collection if destination is an array, We won't change array just same behavior as AutoMapper.
return (TDestination)result;
}
//Return the destination if destination exists. The parameter reference equals with return object.
return destination ?? (TDestination)result;
}
protected virtual bool IsCollectionGenericType<TSource, TDestination>(out Type sourceArgumentType, out Type destinationArgumentType, out Type definitionGenericType)

79
framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Specific_ObjectMapper_Tests.cs

@ -30,47 +30,104 @@ public class AbpAutoMapperModule_Specific_ObjectMapper_Tests : AbpIntegratedTest
[Fact]
public void Specific_Object_Mapper_Should_Be_Used_For_Collections_If_Registered()
{
// IEnumerable
_objectMapper.Map<IEnumerable<MyEntity>, IEnumerable<MyEntityDto2>>(new List<MyEntity>()
{
new MyEntity { Number = 42 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var destination = new List<MyEntityDto2>()
{
new MyEntityDto2 { Number = 44 }
};
var returnIEnumerable = _objectMapper.Map<IEnumerable<MyEntity>, IEnumerable<MyEntityDto2>>(
new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, destination);
returnIEnumerable.First().Number.ShouldBe(43);
ReferenceEquals(destination, returnIEnumerable).ShouldBeTrue();
// ICollection
_objectMapper.Map<ICollection<MyEntity>, ICollection<MyEntityDto2>>(new List<MyEntity>()
{
new MyEntity { Number = 42 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var returnICollection = _objectMapper.Map<ICollection<MyEntity>, ICollection<MyEntityDto2>>(
new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, destination);
returnICollection.First().Number.ShouldBe(43);
ReferenceEquals(destination, returnICollection).ShouldBeTrue();
// Collection
_objectMapper.Map<Collection<MyEntity>, Collection<MyEntityDto2>>(new Collection<MyEntity>()
{
new MyEntity { Number = 42 }
}, new Collection<MyEntityDto2>() //When mapping to an existing collection, the destination collection is cleared first
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var destination2 = new Collection<MyEntityDto2>()
{
new MyEntityDto2 { Number = 44 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
};
var returnCollection = _objectMapper.Map<Collection<MyEntity>, Collection<MyEntityDto2>>(
new Collection<MyEntity>()
{
new MyEntity { Number = 42 }
}, destination2);
returnCollection.First().Number.ShouldBe(43);
ReferenceEquals(destination2, returnCollection).ShouldBeTrue();
// IList
_objectMapper.Map<IList<MyEntity>, IList<MyEntityDto2>>(new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, new Collection<MyEntityDto2>() //When mapping to an existing collection, the destination collection is cleared first
{
new MyEntityDto2 { Number = 44 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var returnIList = _objectMapper.Map<IList<MyEntity>, IList<MyEntityDto2>>(
new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, destination);
returnIList.First().Number.ShouldBe(43);
ReferenceEquals(destination, returnIList).ShouldBeTrue();
// List
_objectMapper.Map<List<MyEntity>, List<MyEntityDto2>>(new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, new List<MyEntityDto2>() //When mapping to an existing collection, the destination collection is cleared first
{
new MyEntityDto2 { Number = 44 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var returnList = _objectMapper.Map<List<MyEntity>, List<MyEntityDto2>>(
new List<MyEntity>()
{
new MyEntity { Number = 42 }
}, destination);
returnList.First().Number.ShouldBe(43);
ReferenceEquals(destination, returnList).ShouldBeTrue();
// Array
_objectMapper.Map<MyEntity[], MyEntityDto2[]>(new MyEntity[]
{
new MyEntity { Number = 42 }
}, new MyEntityDto2[] //When mapping to an existing collection, the destination collection is cleared first
{
new MyEntityDto2 { Number = 44 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var destinationArray = new MyEntityDto2[]
{
new MyEntityDto2 { Number = 40 }
};
var returnArray = _objectMapper.Map<MyEntity[], MyEntityDto2[]>(new MyEntity[]
{
new MyEntity { Number = 42 }
}, destinationArray);
returnArray.First().Number.ShouldBe(43);
// array should not be changed. Same as AutoMapper.
destinationArray.First().Number.ShouldBe(40);
ReferenceEquals(returnArray, destinationArray).ShouldBeFalse();
}
[Fact]

Loading…
Cancel
Save