Browse Source

Resolved #599: Introduce IMapTo and IMapFrom interfaces to allow object map itself

pull/603/head
Halil ibrahim Kalkan 8 years ago
parent
commit
8bd6842043
  1. 36
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
  2. 7
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IMapFrom.cs
  3. 9
      framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IMapTo.cs
  4. 39
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Specific_ObjectMapper_Tests.cs
  5. 44
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityDtoWithMappingMethods.cs

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

@ -1,5 +1,5 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.ObjectMapping
@ -22,7 +22,6 @@ namespace Volo.Abp.ObjectMapping
return default;
}
//Check if a specific mapper is registered
using (var scope = _serviceProvider.CreateScope())
{
var specificMapper = scope.ServiceProvider.GetService<IObjectMapper<TSource, TDestination>>();
@ -32,6 +31,26 @@ namespace Volo.Abp.ObjectMapping
}
}
if (source is IMapTo<TDestination> mapperSource)
{
return mapperSource.MapTo();
}
if (typeof(IMapFrom<TSource>).IsAssignableFrom(typeof(TDestination)))
{
try
{
//TODO: Check if TDestination has a proper constructor which takes TSource
//TODO: Check if TDestination has an empty constructor (in this case, use MapFrom)
return (TDestination) Activator.CreateInstance(typeof(TDestination), source);
}
catch
{
//TODO: Remove catch when TODOs are implemented above
}
}
return AutoMap<TSource, TDestination>(source);
}
@ -42,7 +61,6 @@ namespace Volo.Abp.ObjectMapping
return default;
}
//Check if a specific mapper is registered
using (var scope = _serviceProvider.CreateScope())
{
var specificMapper = scope.ServiceProvider.GetService<IObjectMapper<TSource, TDestination>>();
@ -52,6 +70,18 @@ namespace Volo.Abp.ObjectMapping
}
}
if (source is IMapTo<TDestination> mapperSource)
{
mapperSource.MapTo(destination);
return destination;
}
if (destination is IMapFrom<TSource> mapperDestination)
{
mapperDestination.MapFrom(source);
return destination;
}
return AutoMap(source, destination);
}

7
framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IMapFrom.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.ObjectMapping
{
public interface IMapFrom<in TSource>
{
void MapFrom(TSource source);
}
}

9
framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IMapTo.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.ObjectMapping
{
public interface IMapTo<TDestination>
{
TDestination MapTo();
void MapTo(TDestination destination);
}
}

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

@ -1,3 +1,4 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.AutoMapper.SampleClasses;
@ -21,5 +22,43 @@ namespace Volo.Abp.AutoMapper
var dto = _objectMapper.Map<MyEntity, MyEntityDto2>(new MyEntity { Number = 42 });
dto.Number.ShouldBe(43); //MyEntityToMyEntityDto2Mapper adds 1 to number of the source.
}
[Fact]
public void Should_Use_Destination_Object_Constructor_If_Available()
{
var id = Guid.NewGuid();
var dto = _objectMapper.Map<MyEntity, MyEntityDtoWithMappingMethods>(new MyEntity { Number = 42, Id = id});
dto.Key.ShouldBe(id);
dto.No.ShouldBe(42);
}
[Fact]
public void Should_Use_Destination_Object_MapFrom_Method_If_Available()
{
var id = Guid.NewGuid();
var dto = new MyEntityDtoWithMappingMethods();
_objectMapper.Map(new MyEntity { Number = 42, Id = id }, dto);
dto.Key.ShouldBe(id);
dto.No.ShouldBe(42);
}
[Fact]
public void Should_Use_Source_Object_Method_If_Available_To_Create_New_Object()
{
var id = Guid.NewGuid();
var entity = _objectMapper.Map<MyEntityDtoWithMappingMethods, MyEntity>(new MyEntityDtoWithMappingMethods{Key = id, No = 42});
entity.Id.ShouldBe(id);
entity.Number.ShouldBe(42);
}
[Fact]
public void Should_Use_Source_Object_Method_If_Available_To_Map_Existing_Object()
{
var id = Guid.NewGuid();
var entity = new MyEntity();
_objectMapper.Map(new MyEntityDtoWithMappingMethods { Key = id, No = 42 }, entity);
entity.Id.ShouldBe(id);
entity.Number.ShouldBe(42);
}
}
}

44
framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/SampleClasses/MyEntityDtoWithMappingMethods.cs

@ -0,0 +1,44 @@
using System;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.AutoMapper.SampleClasses
{
//TODO: Move tests to Volo.Abp.ObjectMapping test project
public class MyEntityDtoWithMappingMethods : IMapFrom<MyEntity>, IMapTo<MyEntity>
{
public Guid Key { get; set; }
public int No { get; set; }
public MyEntityDtoWithMappingMethods()
{
}
public MyEntityDtoWithMappingMethods(MyEntity entity)
{
MapFrom(entity);
}
public void MapFrom(MyEntity source)
{
Key = source.Id;
No = source.Number;
}
MyEntity IMapTo<MyEntity>.MapTo()
{
return new MyEntity
{
Id = Key,
Number = No
};
}
void IMapTo<MyEntity>.MapTo(MyEntity destination)
{
destination.Id = Key;
destination.Number = No;
}
}
}
Loading…
Cancel
Save