C# 自动映射MapFrom无效
编辑:添加带有参数信息的构造函数 我使用的是AutoMapper 9.0版和.Net Core 2.1版 下面的单元测试应该更改stockRecord.ClosePrice的值,但如果存在第二个构造函数,则不会更改。注释掉后,第二个构造函数C# 自动映射MapFrom无效,c#,automapper,C#,Automapper,编辑:添加带有参数信息的构造函数 我使用的是AutoMapper 9.0版和.Net Core 2.1版 下面的单元测试应该更改stockRecord.ClosePrice的值,但如果存在第二个构造函数,则不会更改。注释掉后,第二个构造函数closePrice的正确值为100 股票记录类 [DynamoDBTable("StockRecord")] public class StockRecord { [DynamoDBHashKey] public string TickerS
closePrice
的正确值为100
股票记录类
[DynamoDBTable("StockRecord")]
public class StockRecord
{
[DynamoDBHashKey]
public string TickerSymbol { get; set; }
[DynamoDBRangeKey]
public DateTime TradingDay { get; private set; }
public float OpenPrice { get; private set; }
public float ClosePrice { get; private set; }
public float DayHighestPrice { get; private set; }
public float DayLowestPrice { get; private set; }
public StockRecord() {}
// add this constructor below will make the unit test below fail, ClosePrice will stay value of 20
// Once Comment out this constructor, unit test will pass, ClosePrice value will change to 100
public StockRecord(string tickerSymbol, DateTime tradingDay, float openPrice, float closePrice, float dayHighestPrice, float dayLowestPrice)
{
TickerSymbol = tickerSymbol;
TradingDay = tradingDay;
OpenPrice = openPrice;
ClosePrice = closePrice;
DayHighestPrice = dayHighestPrice;
DayLowestPrice = dayLowestPrice;
}
}
StockRecordDto类
public class StockRecordDto
{
public string TickerSymbol { get; set; }
public DateTime TradingDay { get; set; }
public float OpenPrice { get; set; }
public float ClosePrice { get; set; }
public float DayHighestPrice { get; set; }
public float DayLowestPrice { get; set; }
}
单元测试
[Fact]
public void Test1()
{
var configuration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<StockRecord, StockRecordDto>()
.ForMember(dst => dst.ClosePrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 300 : 400))
.ReverseMap()
.ForMember(dst => dst.ClosePrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 100 : 200));
});
configuration.AssertConfigurationIsValid();
var mapper = configuration.CreateMapper();
var stockRecordDto = new StockRecordDto
{
TickerSymbol = "ticker 01",
TradingDay = DateTime.Now,
OpenPrice = 10,
ClosePrice = 20,
DayHighestPrice = 30,
DayLowestPrice = 5
};
StockRecord stockRecord = mapper.Map<StockRecord>(stockRecordDto);
Assert.Equal(100, stockRecord.ClosePrice);
}
[事实]
公共void Test1()
{
var配置=新的MapperConfiguration(cfg=>
{
cfg.CreateMap()
.ForMember(dst=>dst.ClosePrice,op=>op.MapFrom(src=>src.ClosePrice>0?300:400))
.ReverseMap()
.ForMember(dst=>dst.ClosePrice,op=>op.MapFrom(src=>src.ClosePrice>0-100:200));
});
assertConfigurationsValid();
var mapper=configuration.CreateMapper();
var stockRecordDto=新的stockRecordDto
{
TickerSymbol=“ticker 01”,
TradingDay=日期时间。现在,
OpenPrice=10,
收盘价=20,
日最高价格=30,
日最低价格=5
};
StockRecord=mapper.Map(stockRecordDto);
断言。相等(100,股票记录。收盘价);
}
根据autoMapper的文档,stockRecord.ClosePrice应更改为100。但现在仍然是20岁。
我花了整个下午的时间在这上面,但还是想不出来。
我可以用工厂方法替换构造函数,但我仍然不理解为什么带参数的构造函数会出现问题
如果这是一个bug,我会在AutoMapper的github上发布一个问题
谢谢。如果您想更改
DayLowestPrice
,那么在映射中,使用“作为目标”字段DayLowestPrice
,而不是ClosePrice
:
cfg.CreateMap<StockRecord, StockRecordDto>()
.ForMember(dst => dst.DayLowestPrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 300 : 400))
.ReverseMap()
.ForMember(dst => dst.DayLowestPrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 100 : 200));
说明你的目标需要如何构造。您可以找到有关它在上的行为方式的更多信息
Edit2:
您也可以使用ConstructUsing
,但在这种情况下,您应该将属性设置为只读(从属性中删除private set;
),并指定所有构造函数参数。在这种情况下,可以避免硬编码构造函数参数名
public class StockRecord
{
***
public float ClosePrice { get; }
***
}
cfg.CreateMap<StockRecordDto, StockRecord>()
.ConstructUsing(s => new StockRecord(s.TickerSymbol, s.TradingDay, s.OpenPrice, s.ClosePrice > 0 ? 100 : 200, s.DayHighestPrice, s.DayLowestPrice));
公共类股票记录
{
***
公共价格{get;}
***
}
cfg.CreateMap()
.构造使用(s=>新股票记录(s.TickerSymbol,s.TradingDay,s.OpenPrice,s.ClosePrice>0?100:200,s.DayHighestPrice,s.DayLowestPrice));
如果要更改DayLowestPrice
,则在映射中使用“作为目标”字段DayLowestPrice
,而不是ClosePrice
:
cfg.CreateMap<StockRecord, StockRecordDto>()
.ForMember(dst => dst.DayLowestPrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 300 : 400))
.ReverseMap()
.ForMember(dst => dst.DayLowestPrice, op => op.MapFrom(src => src.ClosePrice > 0 ? 100 : 200));
说明你的目标需要如何构造。您可以找到有关它在上的行为方式的更多信息
Edit2:
您也可以使用ConstructUsing
,但在这种情况下,您应该将属性设置为只读(从属性中删除private set;
),并指定所有构造函数参数。在这种情况下,可以避免硬编码构造函数参数名
public class StockRecord
{
***
public float ClosePrice { get; }
***
}
cfg.CreateMap<StockRecordDto, StockRecord>()
.ConstructUsing(s => new StockRecord(s.TickerSymbol, s.TradingDay, s.OpenPrice, s.ClosePrice > 0 ? 100 : 200, s.DayHighestPrice, s.DayLowestPrice));
公共类股票记录
{
***
公共价格{get;}
***
}
cfg.CreateMap()
.构造使用(s=>新股票记录(s.TickerSymbol,s.TradingDay,s.OpenPrice,s.ClosePrice>0?100:200,s.DayHighestPrice,s.DayLowestPrice));
对不起,我是说ClosePrice,我在第一次发布问题时复制了错误的文本。已更新问题。复制粘贴您的代码对我来说效果很好,ClosePrice更改为100。由于您没有提供记录类,我只能猜测,您的ClosePrice
成员StockRecord
上没有setter或private setter。谢谢您的回复。我在课堂上更新了问题。我还发现,是带参数的构造函数导致了问题,一旦我注释掉了第二个构造函数,单元测试就会通过。然而,我只是不明白为什么构造函数会导致这个问题。我需要一天的方式或映射吗?我也进行了测试,即使我通过从StockRecord类中为我的setters取出“private”来公开所有属性,只要带参数的构造函数存在,单元测试就会失败。你可以检查我的编辑,也可以查看文档中的页面。对不起,我是指ClosePrice,当我第一次发布问题时,我抄错了文本。已更新问题。复制粘贴您的代码对我来说效果很好,ClosePrice更改为100。由于您没有提供记录类,我只能猜测,您的ClosePrice
成员StockRecord
上没有setter或private setter。谢谢您的回复。我在课堂上更新了问题。我还发现,是带参数的构造函数导致了问题,一旦我注释掉了第二个构造函数,单元测试就会通过。然而,我只是不明白为什么构造函数会导致这个问题。我需要一天的方式或映射吗?我也进行了测试,即使我通过从StockRecord类中为我的setters取出“private”来公开所有属性,只要带参数的构造函数存在,单元测试就会失败。你可以检查我的编辑,也可以查看文档中的页面。