源中具有只读属性的 AutoMapper 行为未映射到目标
AutoMapper behaviour with readonly properties in source not being mapped to destination
我有一个反向映射的配置,可以将源对象展开为目标对象,但是,如果源对象 属性 是只读的,它会被自动忽略,我必须手动映射它.
我的一些源对象有多达 100 个字段,创建这样的手动映射感觉很麻烦,我不确定为什么自动映射器中存在这种行为。
请参阅下面的代码片段,了解我正在描述的工作示例。
using System;
using AutoMapper;
namespace automappertests
{
class Source
{
public int Field1Suffix1 { get; set; }
public int Field1Suffix2 { get; set; }
public int Field2Suffix1 { get; set; }
// !!Attention!!
// This is a readonly property with a private setter
public int Field2Suffix2 => Field2Suffix1;
}
class Destination
{
public Wrapper Field1 { get; set; }
public Wrapper Field2 { get; set; }
}
class Wrapper
{
public int Suffix1 { get; set; }
public int Suffix2 { get; set; }
public static Wrapper New(int suffix1, int suffix2) =>
new Wrapper
{
Suffix1 = suffix1,
Suffix2 = suffix2
};
}
class DestinationProfile : Profile
{
public DestinationProfile()
{
CreateMap<Destination, Source>()
.ReverseMap()
// !!Attention!!
// Why do I need to have an explicit ForMember MapFrom for the readonly property?
.ForMember(m => m.Field2, o => o.MapFrom(src => Wrapper.New(src.Field2Suffix1, src.Field2Suffix2)));
}
}
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg => { cfg.AddProfile<DestinationProfile>(); });
var mapper = config.CreateMapper();
var source = new Source()
{
Field1Suffix1 = 1,
Field1Suffix2 = 2,
Field2Suffix1 = 3,
};
var destination = mapper.Map<Source, Destination>(source);
Console.WriteLine($"Field1.Suffix1 = {destination.Field1.Suffix1}");
Console.WriteLine($"Field1.Suffix2 = {destination.Field1.Suffix2}");
Console.WriteLine($"Field2.Suffix1 = {destination.Field2.Suffix1}");
Console.WriteLine($"Field2.Suffix2 = {destination.Field2.Suffix2}");
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
}
Output without .ForMember:
Field1.Suffix1 = 1
Field1.Suffix2 = 2
Field2.Suffix1 = 3
Field2.Suffix2 = 0
Output with .ForMember:
Field1.Suffix1 = 1
Field1.Suffix2 = 2
Field2.Suffix1 = 3
Field2.Suffix2 = 3
其实你没有setter。添加显式私有 setter.
public int Field2Suffix2 { get => Field2Suffix1; private set => Field2Suffix1 = value; }
我有一个反向映射的配置,可以将源对象展开为目标对象,但是,如果源对象 属性 是只读的,它会被自动忽略,我必须手动映射它.
我的一些源对象有多达 100 个字段,创建这样的手动映射感觉很麻烦,我不确定为什么自动映射器中存在这种行为。
请参阅下面的代码片段,了解我正在描述的工作示例。
using System;
using AutoMapper;
namespace automappertests
{
class Source
{
public int Field1Suffix1 { get; set; }
public int Field1Suffix2 { get; set; }
public int Field2Suffix1 { get; set; }
// !!Attention!!
// This is a readonly property with a private setter
public int Field2Suffix2 => Field2Suffix1;
}
class Destination
{
public Wrapper Field1 { get; set; }
public Wrapper Field2 { get; set; }
}
class Wrapper
{
public int Suffix1 { get; set; }
public int Suffix2 { get; set; }
public static Wrapper New(int suffix1, int suffix2) =>
new Wrapper
{
Suffix1 = suffix1,
Suffix2 = suffix2
};
}
class DestinationProfile : Profile
{
public DestinationProfile()
{
CreateMap<Destination, Source>()
.ReverseMap()
// !!Attention!!
// Why do I need to have an explicit ForMember MapFrom for the readonly property?
.ForMember(m => m.Field2, o => o.MapFrom(src => Wrapper.New(src.Field2Suffix1, src.Field2Suffix2)));
}
}
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg => { cfg.AddProfile<DestinationProfile>(); });
var mapper = config.CreateMapper();
var source = new Source()
{
Field1Suffix1 = 1,
Field1Suffix2 = 2,
Field2Suffix1 = 3,
};
var destination = mapper.Map<Source, Destination>(source);
Console.WriteLine($"Field1.Suffix1 = {destination.Field1.Suffix1}");
Console.WriteLine($"Field1.Suffix2 = {destination.Field1.Suffix2}");
Console.WriteLine($"Field2.Suffix1 = {destination.Field2.Suffix1}");
Console.WriteLine($"Field2.Suffix2 = {destination.Field2.Suffix2}");
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
}
Output without .ForMember:
Field1.Suffix1 = 1
Field1.Suffix2 = 2
Field2.Suffix1 = 3
Field2.Suffix2 = 0
Output with .ForMember:
Field1.Suffix1 = 1
Field1.Suffix2 = 2
Field2.Suffix1 = 3
Field2.Suffix2 = 3
其实你没有setter。添加显式私有 setter.
public int Field2Suffix2 { get => Field2Suffix1; private set => Field2Suffix1 = value; }