Automapper 合并对象问题
Automapper merging objects issue
在让automapper工作后(),我正在努力解决另一个问题(把它带到另一个问题,所以第一个不会太复杂)...
我有下一个 classes:
public class Model1
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDay { get; set; }
public int Gender { get; set; }
public string NickName { get; set; }
}
public class Model2
{
public bool Married { get; set; }
public int Children { get; set; }
public bool HasPet { get; set; }
}
public class Entity1
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDay { get; set; }
public int Gender { get; set; }
}
public class Entity2
{
public bool Married { get; set; }
public int Children { get; set; }
public bool HasPet { get; set; }
public string NickName { get; set; }
}
除了名称和复杂性之外,这些对象与我的原始对象在原理上相似。
和 AutoMapper 配置 class(从 Global.asax 调用):
public class AutoMapperConfig
{
public static MapperConfiguration MapperConfiguration { get; set; }
public static void Configure()
{
MapperConfiguration = new MapperConfiguration(cfg => {
cfg.AddProfile<Out>();
cfg.CreateMap<SuperModel, SuperEntity>();
});
MapperConfiguration.AssertConfigurationIsValid();
}
}
public class Out: Profile
{
protected override void Configure()
{
CreateMap<Model1, Entity1>();
CreateMap<Model2, Entity2>()
.ForMember(dest => dest.NickName, opt => opt.Ignore());
CreateMap<Model1, Entity2>()
.ForMember(dest => dest.Married, opt => opt.Ignore())
.ForMember(dest => dest.Children, opt => opt.Ignore())
.ForMember(dest => dest.HasPet, opt => opt.Ignore());
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.MapFrom(src => src.Model2));
}
}
当我需要转换对象时,我会做下一步(此时我已经 _superModel
初始化并填充了数据):
SuperEntity _superEntity = new SuperEntity();
AutoMapperConfig.MapperConfiguration.CreateMapper().Map<SuperModel, SuperEntity>(_superModel, _superEntity);
所以,我将 Model1
映射到 Entity1
( 可以),并将 Model2
映射到 Entity2
(也很好,除了 Id 属性,它被忽略了)。
主要对象 SuperModel
和 SuperEntity
也已映射,并且似乎工作正常。
当我将 Model1
映射到 Entity2
以获取 NickName
时,问题发生了(认为其余属性被忽略)。有些怎么总是null
!
有什么想法吗?
问题是您想从多个源 属性 值(Children
、Married
和 HasPet
来自 Model2
和 Nickname
来自 Model1
).
您可以使用 Custom Resolver or with AfterMap 方法解决您的问题。
使用自定义解析器:
您必须创建一个继承自 ValueResolver
的 class 来定义如何从 SuperModel
:
映射 Entity2
public class CustomResolver : ValueResolver<SuperModel, Entity2>
{
protected override Entity2 ResolveCore(SuperModel source)
{
return new Entity2
{
Children = source.Model2.Children,
HasPet = source.Model2.HasPet,
Married = source.Model2.Married,
NickName = source.Model1.NickName
};
}
}
然后,像这样使用它:
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.ResolveUsing<CustomResolver>());
使用 AfterMap:
您可以在映射后执行操作,因此在映射后将值从 Model1.Nickname
传递到 Entity2.Nickname
:
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.MapFrom(src => src.Model2))
.AfterMap((m, e) => e.Entity2.NickName = m.Model1.NickName);
在让automapper工作后(
我有下一个 classes:
public class Model1
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDay { get; set; }
public int Gender { get; set; }
public string NickName { get; set; }
}
public class Model2
{
public bool Married { get; set; }
public int Children { get; set; }
public bool HasPet { get; set; }
}
public class Entity1
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDay { get; set; }
public int Gender { get; set; }
}
public class Entity2
{
public bool Married { get; set; }
public int Children { get; set; }
public bool HasPet { get; set; }
public string NickName { get; set; }
}
除了名称和复杂性之外,这些对象与我的原始对象在原理上相似。
和 AutoMapper 配置 class(从 Global.asax 调用):
public class AutoMapperConfig
{
public static MapperConfiguration MapperConfiguration { get; set; }
public static void Configure()
{
MapperConfiguration = new MapperConfiguration(cfg => {
cfg.AddProfile<Out>();
cfg.CreateMap<SuperModel, SuperEntity>();
});
MapperConfiguration.AssertConfigurationIsValid();
}
}
public class Out: Profile
{
protected override void Configure()
{
CreateMap<Model1, Entity1>();
CreateMap<Model2, Entity2>()
.ForMember(dest => dest.NickName, opt => opt.Ignore());
CreateMap<Model1, Entity2>()
.ForMember(dest => dest.Married, opt => opt.Ignore())
.ForMember(dest => dest.Children, opt => opt.Ignore())
.ForMember(dest => dest.HasPet, opt => opt.Ignore());
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.MapFrom(src => src.Model2));
}
}
当我需要转换对象时,我会做下一步(此时我已经 _superModel
初始化并填充了数据):
SuperEntity _superEntity = new SuperEntity();
AutoMapperConfig.MapperConfiguration.CreateMapper().Map<SuperModel, SuperEntity>(_superModel, _superEntity);
所以,我将 Model1
映射到 Entity1
( 可以),并将 Model2
映射到 Entity2
(也很好,除了 Id 属性,它被忽略了)。
主要对象 SuperModel
和 SuperEntity
也已映射,并且似乎工作正常。
当我将 Model1
映射到 Entity2
以获取 NickName
时,问题发生了(认为其余属性被忽略)。有些怎么总是null
!
有什么想法吗?
问题是您想从多个源 属性 值(Children
、Married
和 HasPet
来自 Model2
和 Nickname
来自 Model1
).
您可以使用 Custom Resolver or with AfterMap 方法解决您的问题。
使用自定义解析器:
您必须创建一个继承自 ValueResolver
的 class 来定义如何从 SuperModel
:
Entity2
public class CustomResolver : ValueResolver<SuperModel, Entity2>
{
protected override Entity2 ResolveCore(SuperModel source)
{
return new Entity2
{
Children = source.Model2.Children,
HasPet = source.Model2.HasPet,
Married = source.Model2.Married,
NickName = source.Model1.NickName
};
}
}
然后,像这样使用它:
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.ResolveUsing<CustomResolver>());
使用 AfterMap:
您可以在映射后执行操作,因此在映射后将值从 Model1.Nickname
传递到 Entity2.Nickname
:
CreateMap<SuperModel, SuperEntity>()
.ForMember(dest => dest.Entity1, opt => opt.MapFrom(src => src.Model1))
.ForMember(dest => dest.Entity2, opt => opt.MapFrom(src => src.Model2))
.AfterMap((m, e) => e.Entity2.NickName = m.Model1.NickName);