最近、Automapper 4.2.1 から 5.1.1 にアップグレードしましたが、オープン ジェネリックを含む以前の有効なマッピングで問題が発生しています。
以前は、automapper 構成内で、次のオープン汎用マッピング構成がありました。
CreateMap(typeof(IPager<>), typeof(ModelPager<>))
.ForMember("Items", e => e.MapFrom(o => (IEnumerable) o));
これは Automapper 4 では機能しますが、InvalidOperaionException
経由でマッピングしようとすると5 で失敗しますIMapper.Map<TDestination>(source)
。アイテム 操作のマッピングを実行すると、「シーケンスには一致する要素が含まれていません」ForMember
という例外メッセージが表示されて失敗するようです。
以下の実装コードの例に反映されているように、
IPager<TSource>
implementsIEnumerable<TSource>
と のItems
プロパティはModelPager<TDestination>
であるIEnumerable<TDestination>
ため、キャストは有効である必要があります。TSource
そして、それぞれに有効なマッピングが存在しますTDestination
CreateMap<TSource, TDestination>();
IPagerインターフェイス
public interface IPager<out TItem> : IEnumerable<TItem>
{
int CurrentPage { get; }
int PageCount { get; }
int PageSize { get; }
int TotalItems { get; }
}
IPager の実装
public class Pager<TItem> : IPager<TItem>
{
private readonly IEnumerable<TItem> _items;
public Pager(IEnumerable<TItem> items,
int currentPage,
int pageSize,
int totalItems)
{
/// ... logic ...
this._items = items ?? Enumerable.Empty<TItem>();
this.CurrentPage = currentPage;
this.PageSize = pageSize;
this.TotalItems = totalItems;
}
public int CurrentPage { get; }
public int PageCount => (this.TotalItems + this.PageSize - 1) / this.PageSize;
public int PageSize { get; }
public int TotalItems { get; }
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
public IEnumerator<TItem> GetEnumerator() => this._items.GetEnumerator();
}
モデルページャー
public class ModelPager<TItem>
{
public int CurrentPage { get; set; }
public IEnumerable<TItem> Items { get; set; }
public int PageCount { get; set; }
public int PageSize { get; set; }
public int TotalItems { get; set; }
}
Automapper 5 でこれをマップする適切な方法は、可能な各マッピングを明示的にマッピングすることによってオープン ジェネリックを放棄するか、すべてのプロパティを手動でマップし、リフレクションを使用してオープン タイプを解決する必要があるカスタム オープン ジェネリック型コンバーターを使用することです。割り当て?