9

私は、Automapper投影法をEntity Framework IQueryablesで使用しようとしています。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()'を使うと、ジェネリック型のパラメータを追加し、マッパー設定をパラメータとして提供する必要があります。あなたはあなたの非常に不完全な質問のコードにそれらのニガーを持っています。 Btw:私は '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インターフェイスを実装しておらず、ProjectToの正しいオーバーロードが受け入れられるものです(IConfigurationProvider)。しかし、ProjectToの別のオーバーロードがあり、これには "object parameters"を使用できます。これはオブジェクトを受け入れるため、他のオーバーロードに適合しないものと一致します。あなたが実際に呼び出すのはProjectTo(object)の過負荷です。これは設定とは無関係で、IMapperConfigurationとプロファイルとマップは完全に無視されます。

クイックフィックスが

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をデザインしない方法を示しています。多くの過負荷があり、そのうちの1つが汎用オブジェクトを受け入れるときはいつもは他のすべての過負荷とは異なるものです - それは問題を求めています。

+0

優れた答え。ありがとう! –

関連する問題