C# 防止AutoMapper在LINQ ProjectTo中将字符串视为集合

C# 防止AutoMapper在LINQ ProjectTo中将字符串视为集合,c#,automapper,C#,Automapper,我要映射以下一组类(仅在一个方向上,从Data*到Api*): //顶层 公共类数据实体 { 公共嵌套数据实体嵌套{get;set;} //…其他基本/复杂属性 } 公共类实体 { 公共嵌套实体嵌套{get;set;} //…其他基本/复杂属性 } //嵌套级别 公共类嵌套数据实体 { 公共字符串项{get;set;} } 公共类嵌套实体 { 公共IEnumerable项{get;set;} } 公共类子项 { //这里有一些属性。为了举例,不需要 } 映射在配置文件中配置,如下代码位所示:

我要映射以下一组类(仅在一个方向上,从
Data*
Api*
):

//顶层
公共类数据实体
{
公共嵌套数据实体嵌套{get;set;}
//…其他基本/复杂属性
}
公共类实体
{
公共嵌套实体嵌套{get;set;}
//…其他基本/复杂属性
}
//嵌套级别
公共类嵌套数据实体
{
公共字符串项{get;set;}
}
公共类嵌套实体
{
公共IEnumerable项{get;set;}
}
公共类子项
{
//这里有一些属性。为了举例,不需要
}
映射在
配置文件中配置,如下代码位所示:

//映射配置文件
公共类MyCustomProfile:Profile
{
公共MyCustomProfile()
{
CreateMap();
CreateMap();
CreateMap()
.ConvertUsing();
}
}
//类型转换器定义
公共类TextToSubItemsConverter:
IT类型转换器
{
公共IEnumerable转换(
字符串数据项、IEnumerable API项、ResolutionContext上下文)
{
//实际上,反序列化并返回ApiSubItem[]
//这里只返回一些固定数组
返回新的ApiSubItem[]
{
新建ApiSubItem(),
新建ApiSubItem(),
新建ApiSubItem(),
};
}
}
//主要
公共课程
{
公共静态void Main(字符串[]args)
{
Mapper.Initialize(cfg=>
{
AddProfile();
});
assertConfigurationsValid();
DataEntity DataEntity=新的DataEntity()
{
嵌套=新的嵌套数据实体()
{
Items=“忽略的文本”,
},
};
//这张地图很好,没有问题
ApiEntity ApiEntity=Mapper.Map(数据实体);
IQueryable dataEntities=new[]{dataEntity}.AsQueryable();
//这将向ApiSubItem问题公开System.Char
ApiEntity apiEntityProjected=dataEntities.ProjectTo().First();
}
}
映射配置在启动时通过初始验证,但当需要实际映射时,我得到异常:

System.InvalidOperationException:缺少从System.Char到my.Anwhere.namespace.ApiSubItem的映射。使用Mapper.CreateMap创建

如果我完全省略了
string
IEnumerable
之间的配置,则初始验证会抱怨相同的上下文:

背景: 从System.Char类型映射到my.Anwhere.namespace.ApiSubItem

虽然当添加,它似乎没有拿起汽车制造商

映射发生在静态上下文中,通过
ProjectTo()
调用
DbSet
上的LINQ查询。我已经检查过转换器不需要任何依赖项,以防万一

AutoMapper是5.0.2,在ASP.NETCore1RTM下的MVCAPI web应用程序中运行

我已经检查了类似的问题,但没有运气。有人知道如何让这种场景工作吗?我想我不是第一个尝试(自动)从
字符串映射到集合的人。助教

EDIT在示例中添加了失败案例和非失败案例

编辑2进一步搜索后,有人建议忽略该字段并在
AfterMap()
中执行映射。使用此配置文件时,不会引发异常,但生成的
字段为空:

CreateMap<DataEntity, ApiEntity>();
CreateMap<NestedDataEntity, NestedApiEntity>()
    .ForMember(api => api.Items, options => options.Ignore())
    .AfterMap((data, api) =>
    {
        api.Items = Mapper.Map<IEnumerable<ApiSubItem>>(data.Items);
    });

CreateMap<string, IEnumerable<ApiSubItem>>()
    .ConvertUsing<TextToSubItemsConverter>();
CreateMap();
CreateMap()
.ForMember(api=>api.Items,options=>options.Ignore())
.AfterMap((数据,api)=>
{
api.Items=Mapper.Map(data.Items);
});
CreateMap()
.ConvertUsing();

编辑3重新编写问题标题,使其更具体地用于投影

我猜实际答案大致是“投影和转换器/分解器不能很好地结合在一起”。从AutoMapper wiki:

并非所有映射选项都可以支持,因为生成的表达式必须由LINQ提供程序解释。[……]

不支持:

  • [……]
  • 前/后地图
  • 自定义解析器
  • 自定义类型转换器
编辑解决方法:
在这个特定的场景中,我后来发现有一个中间DTO实体非常有用,它可以获取更多的字段,这对于最终的API实体来说不是必需的,但是对于业务逻辑来说仍然是必需的

在这样的DTO实体中,我将
字符串
字段保留为
数据实体
,因此我可以使用投影,让AutoMapper/LinqToSQL只从数据库中获取所需的字段


然后,在内存中已有的DTO实体和API实体之间,我可以应用第二个映射,它还利用了
string==>IEnumerable
映射的自定义转换器。HTH

您不能将字符串映射到集合,在这种情况下,您需要打包返回类型为字符串的items.propertyname。因为automapper在一对一映射中工作,所以你能做一个@PankajGupta吗?你能不能再告诉我一次,我不能得到它。@SamIam核心位在那里,现在我编辑了这个问题,添加了一个完整的示例。请让我知道,如果您认为有其他部分缺少@downvoter,请解释动机,以便至少改进问题