9

我想在實體框架IQueryables上使用Automapper投影。Automapper 4.2.1 LINQ投影僅適用於靜態Mapper.CreateMap?

在應用程序啓動時,我創建並添加了所有使用非靜態CreateMap方法創建映射的映射配置文件。

所有這些配置文件都在我的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(); 
+0

發佈您的代碼示例 –

+0

添加我的個人資料..它應該工作嗎?或者是否知道投影僅在使用靜態API時才起作用? –

+0

當我使用'ProjectTo()'時,我必須添加一個泛型類型參數並提供一個映射器配置作爲參數。你有非常不完整的問題代碼中的那些人。順便說一句:我使用'使用AutoMapper.QueryableExtensions;'爲了得到我的'ProjectTo'重載擴展 – grek40

回答

10

原因是以下塊:

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(接口)的實例。你認爲它會有相同的效果,但它不會。 IMapperConfiguration接口不實現IConfigurationProvider接口,那(IConfigurationProvider)是ProjectTo接受的正確過載。但是,ProjectTo有另一個超載,它接受「object parameters」。因爲它接受對象 - 它將匹配任何不適合其他重載的東西。所以你真正打電話的是ProjectTo(object)過載,這與配置無關,你的IMapperConfiguration與配置文件和地圖一起被完全忽略。

的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。無論何時你有許多重載,其中一個接受通用對象,並且完全不同於所有其他重載 - 這就是在尋求麻煩。

+0

優秀的答案。謝謝! –