C# 自动映射到CustomCollection的列表
我正在尝试映射2个实体。一个是字符串列表,另一个是使用自定义集合。谁能告诉我如何使用AutoMapper映射这两个实体C# 自动映射到CustomCollection的列表,c#,automapper,C#,Automapper,我正在尝试映射2个实体。一个是字符串列表,另一个是使用自定义集合。谁能告诉我如何使用AutoMapper映射这两个实体 public class SourceItem { public string Name { get; set; } public List<string> ShipsTo { get; set; } } public class DestItem { public string Name { get; set; } publ
public class SourceItem
{
public string Name { get; set; }
public List<string> ShipsTo { get; set; }
}
public class DestItem
{
public string Name { get; set; }
public MyCollection ShipsTo { get; set; }
}
public class MyCollection : CollectionBase
{
private readonly List<string> _list;
public MyCollection()
{
_list = new List<string>();
}
public MyCollection(List<string> list)
{
_list = list;
}
public void Add(string item)
{
_list.Add(item);
}
}
public类SourceItem
{
公共字符串名称{get;set;}
公共列表ShipsTo{get;set;}
}
公共类目的地
{
公共字符串名称{get;set;}
公共MyCollection ShipsTo{get;set;}
}
公共类MyCollection:CollectionBase
{
私有只读列表_List;
公共MyCollection()
{
_列表=新列表();
}
公共MyCollection(列表)
{
_列表=列表;
}
公共无效添加(字符串项)
{
_列表。添加(项目);
}
}
这是我的映射代码
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SourceItem, DestItem>()
.ForMember(d => d.ShipsTo, o => o.ResolveUsing<CustomResolver>());
});
Mapper.Initialize(cfg=>
{
cfg.CreateMap()
.ForMember(d=>d.ShipsTo,o=>o.resolvesusing());
});
下面是我的自定义解析器的外观
public class CustomResolver : IValueResolver<SourceItem, DestItem, MyCollection>
{
public MyCollection Resolve(SourceItem source, DestItem destination, MyCollection destMember, ResolutionContext context)
{
return new MyCollection(source.ShipsTo);
}
}
公共类CustomResolver:IValueResolver
{
公共MyCollection解析(SourceItem源、DestinItem目标、MyCollection destMember、ResolutionContext上下文)
{
返回新的MyCollection(source.ShipsTo);
}
}
当我试图运行这段代码时,我得到一个错误
类型之间未定义强制运算符
'System.Collections.Generic.List'1[System.Object]'和'MyCollection'
非常感谢您的帮助。我无法真正解释它,但如果您定义从
MyCollection
到MyCollection
的显式映射配置,它是有效的:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<MyCollection, MyCollection>().ConvertUsing((a,b)=>a);
cfg.CreateMap<SourceItem, DestItem>()
.ForMember(d => d.ShipsTo, o => o.ResolveUsing<CustomResolver>());
});
Mapper.Initialize(cfg=>
{
CreateMap().ConvertUsing((a,b)=>a);
cfg.CreateMap()
.ForMember(d=>d.ShipsTo,o=>o.resolvesusing());
});
我已经调试了automapper的代码以找到原因。原因是,Automapper正在寻找合适的映射器,以将MyCollection
映射到MyCollection
。它在所有映射器(在配置中定义并预定义)的集合中查找。实际上,它应该找到一个AssignableMapper
,它只是将一个变量分配给另一个变量,但首先他检查了一个EnumerableMapper
,它看起来还可以,因为您的CollectionBase
是Enumerable
。异常来自此EnumerableMapper
,因为它无法映射这两个集合。解决方案是显式定义,即只需将一个变量分配给另一个变量
但是。我同意谢尔盖的观点。这是一些丑陋的bug,我建议的是完全相同的丑陋解决方法。但我已经设法让它工作:)我看不出您需要自定义解析器,请尝试以下方法:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SourceItem, DestItem>()
.ForMember(d => d.ShipsTo, o => o.MapFrom(src => new MyCollection(src.ShipsTo)));
});
Mapper.Initialize(cfg=>
{
cfg.CreateMap()
.ForMember(d=>d.ShipsTo,o=>o.MapFrom(src=>newmyCollection(src.ShipsTo));
});
答案是:您不能在这里使用自定义值解析器,因为有一个bug(我已经添加了项,您可以跟踪它)。但是您可以按照Jimmy的建议指定List
和MyCollection
之间的转换。一切都会很好:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<List<string>, MyCollection>().ConvertUsing(s => new MyCollection(s));
cfg.CreateMap<SourceItem, DestItem>();
});
Mapper.Initialize(cfg=>
{
CreateMap().ConvertUsing(s=>newmyCollection);
CreateMap();
});
顺便说一句,这个问题似乎已经解决了,应该可以在Automapper的下一个版本中使用。似乎Automapper有bug。但是不管怎样-为什么您需要继承
CollectionBase
?@SergeyBerezovskiy这只是一个例子。事实上,我使用的是第三方API(eBay SDK),他们有很多使用CollectionBase的集合,就像我发布的示例一样。我无法更改他们的自定义集合。错误会消失,但没有映射-MyCollection是empty@SergeyBerezovskiy我已经更改了答案,现在在我的示例中它工作了。建议的代码没有给出错误,但MyCollection仍然是空的。即使在执行了.ForMember之后(d=>d.ShipsTo,o=>o.MapFrom(src=>newmyCollection(src.ShipsTo));Debuggin显示出于某种原因,MyCollection被调用了两次。第一次使用MyCollection(src.ShipsTo)将项目添加到列表中,第二次调用重新启动列表的默认构造函数。@nafr1如何看待该集合?您的代码继承collectionBase,但不使用它。你们应该查看私有列表属性,它是设置好的,在我映射它之后。我想你们是对的,他在试图避免异常的customresolver中写道。你也可以通过你的代码得到它。