Ответ 1
Я решил это, используя комбинацию метода ResolveUsing<T>()
и внедряя IValueResolver
и ConvertUsing<T>()
метод и реализуя ITypeConverter<TSource,TDestination>
.
Некоторые из моих сценариев сопоставления более сложны, чем обычно, включая двунаправленное сопоставление и вложенные классы и вложенные коллекции. Это помогло мне решить их.
ИЗМЕНИТЬ
В соответствии с запросом я включил пример решения. Этот пример намного проще, чем фактические типы, с которыми я имел дело.
using System;
using AutoMapper;
namespace TestAutoMapperComplex
{
public class Dto
{
public string Property { get; set; }
public string SubProperty { get; set; }
}
public class Entity
{
public string Property { get; set; }
public SubEntity Sub { get; set; }
}
public class SubEntity
{
public string SubProperty { get; set; }
}
static class MapperConfig
{
public static void Initialize()
{
Mapper.CreateMap<Dto, Entity>()
.ForMember(entity => entity.Sub, memberOptions =>
memberOptions.MapFrom(dto => dto));
Mapper.CreateMap<Dto, SubEntity>();
}
}
static class MapperConfig2
{
private class MyResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
var destinationSubEntity = ((Entity)source.Context.DestinationValue).Sub;
Mapper.Map((Dto)source.Value, destinationSubEntity);
return source.New(destinationSubEntity, typeof(SubEntity));
}
}
public static void Initialize()
{
Mapper.CreateMap<Dto, Entity>()
.ForMember(entity => entity.Sub, memberOptions =>
memberOptions.ResolveUsing<MyResolver>());
Mapper.CreateMap<Dto, SubEntity>();
}
}
class Program
{
static void Main(string[] args)
{
MapperConfig.Initialize();
var dto = new Dto {Property = "Hello", SubProperty = "World"};
var subEntity = new SubEntity {SubProperty = "Universe"};
var entity = new Entity {Property = "Good bye", Sub = subEntity};
Mapper.Map(dto, entity);
Console.WriteLine(string.Format("entity.Property == {0}, entity.Sub.SubProperty == {1}",
entity.Property, entity.Sub.SubProperty));
Console.WriteLine(string.Format("entity.Sub == subEntity: {0}",
entity.Sub == subEntity));
}
}
}
Если вы запустите пример, который использует MapperConfig
, вы получите следующий вывод:
entity.Property == Hello, entity.Sub.SubProperty == World
entity.Sub == subEntity: False
Все свойства строки все обновляются, как хотелось бы, но entity.Sub
заменяется новым экземпляром SubEntity
, который не подходит для того, когда вы хотите обновлять объекты для ORM, которые будут сохраняться базы данных.
Если вы измените Main
так, чтобы вместо этого использовался MapperConfig2
, вы все равно сохраните свойства строки, как и раньше, , но, entity.Sub
все еще имеет тот же экземпляр SubEntity
что это было раньше. Запуск примера с помощью MapperConfig2
дает этот результат:
entity.Property == Hello, entity.Sub.SubProperty == World
entity.Sub == subEntity: True
Ключевое различие в MapperConfig2
заключается в том, что ResolveUsing
используется вместе с MyResolver
для сохранения значения entity.Sub
.