我试图弄清楚如何使用AutoMapper处理不可变模型。
主要思想是拥有一个基本模型(在本例中为ModelBase),该模型具有一些将为所有其他模型(在本例中为Person)继承的属性。
基本模型是:
// it's abstract to avoid the developers to create an instance of this class // public abstract class ModelBase { protected ModelBase(Guid id, bool enabled, DateTime createdAt, DateTime? updatedAt, DateTime? deletedAt) { Id = id; Enabled = enabled; CreatedAt = createdAt; UpdatedAt = updatedAt; DeletedAt = deletedAt; }
public Guid Id { get; }
public bool Enabled { get; set; }
public DateTime CreatedAt { get; }
public DateTime? UpdatedAt { get; }
public DateTime? DeletedAt { get; }
} 该模型是:
public class Person : ModelBase { public Person(string name, DateTime birthday, Gender gender) { Name = name; Birthday = birthday; Gender = gender; }
public string Name { get; }
public DateTime Birthday { get; }
public Gender Gender { get; }
} 我尝试通过以下方式映射个人资料:
public class MyProfile : Profile { public MyProfile() { CreateMap<Source.ModelBase, Destination.ModelBase>().IncludeAllDerived(); CreateMap<Source.Person, Destination.Person>().ReverseMap(); } } 但是我不知道该怎么做。我读到有关CustomResolvers,ResolveUsing,ForMember,ForAllMembers的信息,但仍不清楚。你们能帮我解决这个问题吗?
AutoMapper调用Person构造函数不会有任何问题,但ModelBase不会发生这种情况。我在这里想念什么?
谢谢。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在AutoMapper中处理不可变模型时,确实需要一些特殊考虑,因为这些模型的属性通常是只读的,并且通过构造函数进行初始化。对于继承自一个具有私有或受保护构造函数的基本模型(如您的ModelBase
)的情况,您需要确保AutoMapper能够正确地调用这些构造函数来创建对象。
以下是如何使用AutoMapper配置以支持映射到和从不可变模型的方法:
为了确保AutoMapper调用正确的构造函数,您可以使用ConstructUsing
方法显式指定如何创建目标类型的实例。对于ModelBase
及其子类,这可能看起来像这样:
public class MyProfile : Profile
{
public MyProfile()
{
// 显式定义如何构造ModelBase的实例
CreateMap<Guid, ModelBase>()
.ConstructUsing(id => new ModelBase(id, true, DateTime.UtcNow, null, null));
// 对于Person类,先映射到ModelBase,然后映射其他属性
CreateMap<PersonDto, Person>()
.ConstructUsing(dto => new Person(
dto.Id,
dto.Enabled,
DateTime.UtcNow, // 或者根据实际逻辑获取createdAt
null, // 或者相应逻辑处理updatedAt
null)) // 或者相应逻辑处理deletedAt
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.Birthday, opt => opt.MapFrom(src => src.Birthday))
.ForMember(dest => dest.Gender, opt => opt.MapFrom(src => src.Gender));
// 反向映射同样需要处理
CreateMap<Person, PersonDto>();
}
}
这里假设有一个PersonDto
作为数据传输对象(DTO),与Person
实体相对应。请注意,我直接使用了构造参数来匹配ModelBase
的构造函数签名,同时为Person
的特定属性指定了映射规则。
对于不可变对象,ReverseMap()
可能不总是适用,因为它通常假设对象是可变的,可以简单地设置属性值。如果您的Person
类也是不可变的,那么您需要为反向映射也明确指定构造函数和成员映射。
在某些复杂场景下,您可能还需要实现自定义解析器来处理更复杂的逻辑,但这对于基本的构造函数调用和属性映射来说通常是不必要的。
确保AutoMapper能正确处理不可变模型的关键在于利用ConstructUsing
来指导如何实例化目标类型,并且对所有属性使用ForMember
来指定映射规则。对于继承结构,要分别处理基类和派生类的映射逻辑。希望这能帮助您解决当前的问题!