Automapper 和 Nullable 引用类型提高 "needs to have a constructor with 0 args or only optional args"

Automapper and Nullable Reference Type raise "needs to have a constructor with 0 args or only optional args"

场景

我无法将 class 映射到 string 和可为 null 的引用类型 enabled

#r "nuget:AutoFixture/4.17.0"
#r "nuget:AutoMapper/11.0.1"

using AutoFixture;
using AutoMapper;

class Song
{
    public int Id { get; set; }

    public string Title { get; set; }

    public string Content { get; set; }

    public IEnumerable<Tag>? Tags { get; set; }

    public Song()
    {
        Title = string.Empty;
        Content = string.Empty;
    }
}

class Tag
{
    public int Id { get; set; }

    public string Title { get; set; }

    public string Color { get; set; }

    public Tag()
    {
        Title = string.Empty;
        Color = string.Empty;
    }
}


class DetailSong
{
    public string Title { get; set; }

    public string Content { get; set; }

    public IEnumerable<int>? Tags { get; set; }

    public DetailSong(string title, string content, IEnumerable<int>? tags)
    {
        Title = title;
        Content = content;
        Tags = tags;
    }

}

class CreateSong : DetailSong
{
    public string Author { get; set; }

    public CreateSong(string author, string title, string content, IEnumerable<int>? tags) :
        base(title, content, tags)
    {
        Author = author;
    }
}

var config = new MapperConfiguration(cfg =>
{

    cfg.CreateMap<Tag, int>()
                .ConstructUsing(p => p.Id)
                ;

    cfg.CreateMap<Song, CreateSong>()
        .ForMember(p => p.Author, o => o.MapFrom(k => "dummy"))
        .ForMember(p => p.Content, o => o.MapFrom(k => k.Content))
        .ForMember(p => p.Title, o => o.MapFrom(k => k.Title))
        ;

});

var mapper = config.CreateMapper();

Fixture fixture = new Fixture();
var s = fixture.Create<Song>();

// throw needs to have a constructor with 0 args or only optional args. Validate your configuration for details. (Parameter 'type')
var m = mapper.Map<CreateSong>(s);

解决方法

我找到了两个解决方法:

一个

如果我在 CreateMap 上指定 .ForCtorParam("author", o => o.MapFrom(k => "dummy")) 它会正常工作

cfg.CreateMap<Song, CreateSong>()
        .ForCtorParam("author", o => o.MapFrom(k => "dummy")) // <--------
        .ForMember(p => p.Content, o => o.MapFrom(k => k.Content))
        .ForMember(p => p.Title, o => o.MapFrom(k => k.Title))
        
        ;

两个

添加一个 args 0 构造函数

public CreateSong() : base(string.Empty, string.Empty, null)
{
        Author = string.Empty;
}

问题

为什么Automapper可以映射titlecontenttags但不能映射author字段?我怀疑它是否链接到可为空的引用类型。

它与可空引用类型无关。 Automapper is capable of mapping fields/properties to constructor parameters 基于名称,没有匹配 author 参数,因此原始映射失败。 IE。接下来将工作:

cfg.CreateMap<Song, CreateSong>()
    .ForCtorParam("author", o => o.MapFrom(k => "dummy"));

另请注意,ForMember 调用实际上会被忽略。尝试将映射更改为:

cfg.CreateMap<Song, CreateSong>()
    .ForCtorParam("author", o => o.MapFrom(k => "dummy"))
    .ForMember(p => p.Content, o => o.MapFrom(k => k.Content + "_Test"))
    .ForMember(p => p.Title, o => o.MapFrom(k => k.Title + "_Test")) ;

你会发现它不会影响结果。