如何使用AutoMapper将Dto映射到具有嵌套对象的现有对象实例?
我有以下Dto和实体与嵌套的子实体。
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; } }
如何使用AutoMapper设置映射,这将允许我使用Dto中的值更新现有的Entity实例。
我正在使用Mapper.Map(dto, entity)
更新现有实体但是当我尝试将Dto.SubProperty
映射到Entity.Sub.SubProperty
我得到一个例外, “必须解析为顶级成员。参数名称:lambdaExpression “ 。
如果我使用FromMember
创建从SubEntity
到SubEntity
的映射,那么Entity.Sub
将被替换为SubEntity
的新实例,但这不是我想要的。 我只是想让它在Entity
的Sub
属性上更新现有SubEntity
实例的属性。
我怎样才能做到这一点?
我通过结合使用ResolveUsing
方法并实现IValueResolver
和ConvertUsing
方法并实现ITypeConverter
。
我的一些映射场景比正常情况更复杂,包括双向映射和嵌套类以及嵌套集合。 以上帮助我解决了这些问题。
编辑
根据要求,我已经包含了一个示例解决方案。 这个例子比我正在处理的实际类型简单得多。
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() .ForMember(entity => entity.Sub, memberOptions => memberOptions.MapFrom(dto => dto)); Mapper.CreateMap(); } } 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() .ForMember(entity => entity.Sub, memberOptions => memberOptions.ResolveUsing()); Mapper.CreateMap(); } } 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
的主要区别在于MapperConfig2
与MyResolver
一起使用以保留MyResolver
的值。