AutoMapper映射列表与列表派生类时遇参数错误及结果为空问题
AutoMapper映射继承List的自定义列表类问题解决办法
当自定义类ListExtension继承自List<string>,使用AutoMapper在它与List<string>之间映射时,会触发以下错误:
Incorrect number of arguments supplied for call to method System.String 'get_Item(Int32)'
若按照相关方案忽略Item成员,映射虽能执行,但结果为空,测试无法通过。
问题根源
AutoMapper默认会尝试映射类的所有成员,包括集合的索引器Item,但索引器是带参数的属性,AutoMapper处理这类成员时会触发参数错误。而直接忽略Item后,AutoMapper失去了复制集合元素的逻辑,导致目标集合为空。
正确解决方案
不需要忽略Item成员,而是通过自定义映射逻辑,让AutoMapper正确复制集合元素。以下是两种可行方案:
方案1:使用ConstructUsing结合AfterMap
var config = new MapperConfiguration(cfg => { // List<string> → ListExtension cfg.CreateMap<List<string>, ListExtension>() .ConstructUsing(_ => new ListExtension()) .AfterMap((source, dest) => { foreach (var item in source) { dest.Add(item); } }); // ListExtension → List<string>,利用List的构造函数直接复制 cfg.CreateMap<ListExtension, List<string>>() .ConstructUsing(source => new List<string>(source)); });
方案2:利用AutoMapper的集合默认映射(简化版)
由于ListExtension是List<string>的子类,也可以直接让AutoMapper使用集合的默认映射逻辑,仅需确保配置正确:
var config = new MapperConfiguration(cfg => { // 无需额外配置Item,AutoMapper会识别集合类型并处理元素复制 cfg.CreateMap<List<string>, ListExtension>(); cfg.CreateMap<ListExtension, List<string>>(); });
注:若此方案仍触发错误,优先使用方案1的显式映射逻辑。
修正后的测试代码
[Fact] public void Issue1() { var config = new MapperConfiguration(cfg => { cfg.CreateMap<List<string>, ListExtension>() .ConstructUsing(_ => new ListExtension()) .AfterMap((source, dest) => { foreach (var item in source) { dest.Add(item); } }); cfg.CreateMap<ListExtension, List<string>>() .ConstructUsing(source => new List<string>(source)); }); IMapper mapper = config.CreateMapper(); List<string> myList = new List<string> { "0", "1", "2" }; var afterMap = mapper.Map<ListExtension>(myList); Assert.Equal(myList.Count, afterMap.Count); // 可额外验证元素是否一致 Assert.Equal(myList, afterMap); }
内容的提问来源于stack exchange,提问作者Moniker
相关产品推荐
相关产品推荐

