Browse Source

Merge pull request #20829 from abpframework/DefaultObjectMapper

Optimize the way to get `Map` method through reflection.
pull/20854/head
Engincan VESKE 2 years ago
committed by GitHub
parent
commit
6960cedbe4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 38
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
  2. 21
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Specific_ObjectMapper_Tests.cs
  3. 18
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs

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

@ -142,13 +142,39 @@ public class DefaultObjectMapper : IObjectMapper, ITransientDependency
cacheKey,
_ =>
{
return specificMapper
var methods = specificMapper
.GetType()
.GetMethods()
.First(x =>
x.Name == nameof(IObjectMapper<object, object>.Map) &&
x.GetParameters().Length == (destination == null ? 1 : 2)
);
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == nameof(IObjectMapper<object, object>.Map))
.Where(x =>
{
var parameters = x.GetParameters();
if (destination == null && parameters.Length != 1 ||
destination != null && parameters.Length != 2 ||
parameters[0].ParameterType != sourceArgumentType)
{
return false;
}
return destination == null || parameters[1].ParameterType == destinationArgumentType;
})
.ToList();
if (methods.IsNullOrEmpty())
{
throw new AbpException($"Could not find a method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(destination == null ? sourceArgumentType.ToString() : sourceArgumentType + "," + destinationArgumentType)})" +
$" in the type '{mapperType}'.");
}
if (methods.Count > 1)
{
throw new AbpException($"Found more than one method named '{nameof(IObjectMapper<object, object>.Map)}'" +
$" with parameters({(destination == null ? sourceArgumentType.ToString() : sourceArgumentType + "," + destinationArgumentType)})" +
$" in the type '{mapperType}'.");
}
return methods.First();
}
);

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

@ -130,6 +130,27 @@ public class AbpAutoMapperModule_Specific_ObjectMapper_Tests : AbpIntegratedTest
ReferenceEquals(returnArray, destinationArray).ShouldBeFalse();
}
[Fact]
public void Specific_Object_Mapper_Should_Support_Multiple_IObjectMapper_Interfaces()
{
var myEntityDto2 = _objectMapper.Map<MyEntity, MyEntityDto2>(new MyEntity { Number = 42 });
myEntityDto2.Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
var myEntity = _objectMapper.Map<MyEntityDto2, MyEntity>(new MyEntityDto2 { Number = 42 });
myEntity.Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
// 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.
_objectMapper.Map<IEnumerable<MyEntityDto2>, IEnumerable<MyEntity>>(new List<MyEntityDto2>()
{
new MyEntityDto2 { Number = 42 }
}).First().Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
}
[Fact]
public void Should_Use_Destination_Object_Constructor_If_Available()
{

18
framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityToMyEntityDto2Mapper.cs

@ -3,7 +3,7 @@ using Volo.Abp.ObjectMapping;
namespace Volo.Abp.AutoMapper.SampleClasses;
public class MyEntityToMyEntityDto2Mapper : IObjectMapper<MyEntity, MyEntityDto2>, ITransientDependency
public class MyEntityToMyEntityDto2Mapper : IObjectMapper<MyEntity, MyEntityDto2>, IObjectMapper<MyEntityDto2, MyEntity>, ITransientDependency
{
public MyEntityDto2 Map(MyEntity source)
{
@ -20,4 +20,20 @@ public class MyEntityToMyEntityDto2Mapper : IObjectMapper<MyEntity, MyEntityDto2
destination.Number = source.Number + 1;
return destination;
}
public MyEntity Map(MyEntityDto2 source)
{
return new MyEntity
{
Id = source.Id,
Number = source.Number + 1
};
}
public MyEntity Map(MyEntityDto2 source, MyEntity destination)
{
destination.Id = source.Id;
destination.Number = source.Number + 1;
return destination;
}
}

Loading…
Cancel
Save