开发者社区 问答 正文

C#中utomapper-调用基本类型的构造函数以映射基本属性

我试图弄清楚如何使用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不会发生这种情况。我在这里想念什么?

谢谢。

展开
收起
被纵养的懒猫 2019-10-09 17:03:45 474 分享 版权
阿里云 AI 助理回答

在AutoMapper中处理不可变模型时,确实需要一些特殊考虑,因为这些模型的属性通常是只读的,并且通过构造函数进行初始化。对于继承自一个具有私有或受保护构造函数的基本模型(如您的ModelBase)的情况,您需要确保AutoMapper能够正确地调用这些构造函数来创建对象。

以下是如何使用AutoMapper配置以支持映射到和从不可变模型的方法:

1. 使用ConstructUsing

为了确保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的特定属性指定了映射规则。

2. 考虑使用ReverseMap()谨慎

对于不可变对象,ReverseMap()可能不总是适用,因为它通常假设对象是可变的,可以简单地设置属性值。如果您的Person类也是不可变的,那么您需要为反向映射也明确指定构造函数和成员映射。

3. 自定义解析器(Custom Resolver)

在某些复杂场景下,您可能还需要实现自定义解析器来处理更复杂的逻辑,但这对于基本的构造函数调用和属性映射来说通常是不必要的。

总结

确保AutoMapper能正确处理不可变模型的关键在于利用ConstructUsing来指导如何实例化目标类型,并且对所有属性使用ForMember来指定映射规则。对于继承结构,要分别处理基类和派生类的映射逻辑。希望这能帮助您解决当前的问题!

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
C#
问答标签:
问答地址: