gpt4 book ai didi

c# - Automapper 4.2.1 LINQ 投影仅适用于静态 Mapper.CreateMap?

转载 作者:太空狗 更新时间:2023-10-29 17:49:12 29 4
gpt4 key购买 nike

我正在尝试在 Entity Framework IQueryables 上使用 Automapper 投影。

在应用程序启动时,我创建并添加了我所有的映射配置文件,这些配置文件使用非静态 CreateMap 方法创建 map 。

所有这些配置文件都在我的 IoC 容器中注册。

虽然我在我的 mappingConfiguration 实例中看到了映射配置文件,但我得到了丢失的映射异常。

可能是什么问题?我错过了什么吗?我正在使用 Automapper 4.2.1

我注意到添加静态 Mapper.CreateMap 时效果很好。投影是否仅适用于静态 API?我想避免使用静态 API。

完整代码:

public class ItemEntityToItemView : Profile
{
public override void Configure()
{
CreateMap<ItemEntity, ItemView>();

// Without this line, I get missing Map type configuration.
Mapper.CreateMap<ItemEntity, ItemView>();
}
}


public interface IEntitiesProjector
{
IQueryable<T> SelectTo<T>(IQueryable source);
}

public class EntitiesProjector : IEntitiesProjector
{
private readonly IMapperConfiguration _mapperConfig;

public EntitiesProject(IMapperConfiguration mapperConfig)
{
_mapperConfig = mapperConfig;
}

public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}

public class ItemsRepository : IITemsRepository
{
public IQueryable<ItemEntity> GetById(int id)
{
return _dbSet.Where(x => x.Id == id);
}
}

public class Service
{
private readonly IEntitiesProjector _projector;

public Service(IEntitiesProject entitiesProjector)
{
_projector = entitiesProjector;
}

public List<T> GetItem(int id)
{
IQueryable<ItemEntity> itemsQueryable = ItemsRepository.GetById(id);

return _projector.SelectTo<ItemView>(itemsQueryable);
}
}

My Autofac registration :

builder.RegisterAssemblyTypes().AssignableTo(typeof(Profile)).As<Profile>();

builder.Register(c => new MapperConfiguration(cfg =>
{
cfg.CreateMap<IdentityUser, AspNetUser>().ReverseMap();
})).AsSelf().As<IMapperConfiguration>().SingleInstance();

builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve)).As<IMapper>().InstancePerLifetimeScope();

builder.Register<EntitiesProjector>().As<IEntitiesProjector>().SingleInstance();

最佳答案

原因是下面的 block :

public class EntitiesProjector : IEntitiesProjector
{
private readonly IMapperConfiguration _mapperConfig;

public EntitiesProject(IMapperConfiguration mapperConfig)
{
_mapperConfig = mapperConfig;
}

public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}

source.ProjectTo 是一个有 5 个重载的扩展方法。在文档中,他们正在传递 MappingConfiguration 类的实例,而您正在传递 IMapperConfiguration (接口(interface))的实例。你认为它会产生同样的效果,但它并没有。 IMapperConfiguration 接口(interface)不实现 IConfigurationProvider 接口(interface),并且 (IConfigurationProvider) 是 ProjectTo 接受的正确重载。但是,ProjectTo 有另一个重载,它接受“对象参数”。因为它接受对象 - 它会匹配任何不适合其他重载的东西。所以你真正调用的是 ProjectTo(object) 重载,它与配置无关,你的 IMapperConfiguration 连同配置文件和 map 被完全忽略。

Quickfix 将是

public class EntitiesProjector : IEntitiesProjector
{
private readonly IConfigurationProvider _mapperConfig;

public EntitiesProjector(IMapperConfiguration mapperConfig)
{
_mapperConfig = (IConfigurationProvider)mapperConfig;
}

public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}

当然,您最好在容器中将您的配置注册为 IConfigurationProvider,这只是快速修复以确保问题确实存在。

至于静态 Mapper.CreateMap - 它是静态的,因此无论您传递给 ProjectTo 的内容如何,​​它都会起作用。

作为旁注,这向您展示了如何不设计 api。每当您有许多重载并且其中一个接受通用对象并且做完全与所有其他重载不同的事情时 - 这就是自找麻烦。

关于c# - Automapper 4.2.1 LINQ 投影仅适用于静态 Mapper.CreateMap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36566202/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com