Automapper扩展方法
问题描述
系统中实现了一个自定义的PagedList
/// <summary>
/// Paged list interface
/// </summary>
public interface IPagedList
{
int PageIndex { get; }
int PageSize { get; }
int TotalCount { get; }
int TotalPages { get; }
bool HasPreviousPage { get; }
bool HasNextPage { get; }
} /// <summary>
/// Paged list interface
/// </summary>
public interface IPagedList<T> : IList<T>, IPagedList
{
} /// <summary>
/// Paged list
/// </summary>
/// <typeparam name="T">T</typeparam>
[Serializable]
public class PagedList<T> : List<T>, IPagedList<T>
{
/// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
{
int total = source.Count();
this.TotalCount = total;
this.TotalPages = total / pageSize; if (total % pageSize > 0)
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
} /// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
public PagedList(IList<T> source, int pageIndex, int pageSize)
{
TotalCount = source.Count();
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > 0)
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
} /// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalCount">Total count</param>
public PagedList(IEnumerable<T> source, int pageIndex, int pageSize, int totalCount)
{
TotalCount = totalCount;
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > 0)
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source);
} public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; } public bool HasPreviousPage
{
get { return (PageIndex > 0); }
}
public bool HasNextPage
{
get { return (PageIndex + 1 < TotalPages); }
}
}
转换失败,AutoMapper可不认识PagedList
[TestMethod]
public void MapTest2()
{
Mapper.CreateMap<User, UserViewModel>(); var userList = new List<User>()
{
new User() {Name = "Name1", UserId = "UserId1"},
new User() {Name = "Name2", UserId = "UserId2"},
new User() {Name = "Name3", UserId = "UserId3"},
new User() {Name = "Name4", UserId = "UserId4"},
new User() {Name = "Name5", UserId = "UserId5"},
new User() {Name = "Name6", UserId = "UserId6"},
new User() {Name = "Name7", UserId = "UserId7"},
}; var pagedList = new PagedList<User>(userList, 0, 5); Mapper.Map<PagedList<User>, PagedList<UserViewModel>>(pagedList);//Exception }
解决方案
/// <summary>
/// The collection extensions.
/// </summary>
public static class ObjectExtensions
{
private static readonly MethodInfo mapMethod;
private static readonly ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Type>> methodsMapper = new ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Type>>(); static ObjectExtensions()
{
mapMethod = (typeof(Mapper)).GetMethods().FirstOrDefault(_ => _.Name == "Map" && _.GetParameters().Length == 1);
} public static T MapTo<T>(this IPagedList tList) where T : class
{
var totalCount = tList.TotalCount;
var pageIndex = tList.PageIndex;
var pageSize = tList.PageSize; var t = methodsMapper.GetOrAdd(new Tuple<Type, Type>(tList.GetType(), typeof(T)), _ =>
{
var targetGenericArguments = typeof(T).GenericTypeArguments[0];
var targetGenericArgumentsIEnumerableType = typeof(IEnumerable<>).MakeGenericType(targetGenericArguments);
return new Tuple<MethodInfo, Type>(mapMethod.MakeGenericMethod(targetGenericArgumentsIEnumerableType),
typeof(PagedList<>).MakeGenericType(targetGenericArguments));
});
var rtn2 = t.Item1.Invoke(null, new object[] { tList });
var o2 = Activator.CreateInstance(t.Item2, rtn2, pageIndex, pageSize, totalCount) as T;
return o2;
} public static T MapTo<T>(this object o) where T : class
{
//way1
//var mapMethod = (typeof(Mapper)).GetMethods().FirstOrDefault(_ => _.Name == "Map" && _.GetParameters().Length == 1 && _.GetGenericArguments().Length == 2 );
//var m2 = mapMethod.MakeGenericMethod(o.GetType(), typeof (T));
//return m2.Invoke(null, new[] { o }) as T; //way2
return Mapper.Map<T>(o);
} public static void MapTo<S,T>(this S o,T t) where T : class
{
Mapper.Map(o,t);
}
}
测试通过
[TestMethod]
public void MapTest2()
{
Mapper.CreateMap<User, UserViewModel>(); var userList = new List<User>()
{
new User() {Name = "Name1", UserId = "UserId1"},
new User() {Name = "Name2", UserId = "UserId2"},
new User() {Name = "Name3", UserId = "UserId3"},
new User() {Name = "Name4", UserId = "UserId4"},
new User() {Name = "Name5", UserId = "UserId5"},
new User() {Name = "Name6", UserId = "UserId6"},
new User() {Name = "Name7", UserId = "UserId7"},
}; var pagedList = new PagedList<User>(userList, 0, 5);
var vmPagedList = pagedList.MapTo<PagedList<UserViewModel>>();
Assert.IsTrue(vmPagedList.TotalPages == 2
&& vmPagedList.PageSize == 5
&& vmPagedList.PageIndex == 0
); }
总结
运行时动态获取泛型参数并执行Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>,并且使用ConcurrentDictionary缓存MethodInfo提高性能。
Automapper扩展方法的更多相关文章
- AutoMapper 6.x 扩展方法
简介 很多时候我们使用AutoMapper的时候,都需要进行一个配置才可以使用Mapper.Map<Source,Target>(entity);.如果不进行配置则会报错. 如果实体过多, ...
- ABP框架源码中的Linq扩展方法
文件目录:aspnetboilerplate-dev\aspnetboilerplate-dev\src\Abp\Collections\Extensions\EnumerableExtensions ...
- AutoMapper扩展帮助类
/// <summary> /// AutoMapper扩展帮助类 /// </summary> public static class AutoMapperExtension ...
- .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法
.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...
- .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类
.NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...
- 为IEnumerable<T>添加RemoveAll<IEnumerable<T>>扩展方法--高性能篇
最近写代码,遇到一个问题,微软基于List<T>自带的方法是public bool Remove(T item);,可是有时候我们可能会用到诸如RemoveAll<IEnumerab ...
- C#的扩展方法解析
在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继 ...
- 扩展方法(C#)
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 下面的示例为String添加 ...
- 扩展方法解决LinqToSql Contains超过2100行报错问题
1.扩展方法 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...
随机推荐
- 专访Linux嵌入式开发韦东山操作系统图书作者--转
CSDN学院讲师韦东山:悦己之作,方能悦人 发表于2015-04-28 08:09| 6669次阅读| 来源CSDN| 24 条评论| 作者夏梦竹 专访Linux嵌入式开发韦东山操作系统图书作者 摘要 ...
- Android Material Design控件学习(一)——TabLayout的用法
前言 Google官方在14年Google I/O上推出了全新的设计语言--Material Design.一并推出了一系列实现Material Design效果的控件库--Android Desig ...
- java 动态创建数据库和动态连接数据库
项目中有一个需求要动态创建数据库并且要动态连接数据库,本来以为还很难实现呢,在网上找了好久,都不是很理想,最后看到有人说创建数据库时,先连接到任意一个数据库,获得连接后用createStatement ...
- SQL SERVER 使用select和union插入多条数据
insert into A(A) select '2' union select '3' union select '100' go select * from A
- 【转载】Linux i386+源码中常见宏标识tag的定义
转载自:http://blog.chinaunix.net/uid-20729583-id-1884553.html 这 些宏包括 __init.__initdata.__initfunc().asm ...
- .NET通用开发框架
在开源中国社区,简单整理了下比较好的.NET通用开发框架.一个好的通用框架大概包括:开源.扩展性好.灵活性好.复用性好.维护性好.易测试.易发布.易部署.快速业务搭建(或业务集成).通用性强.参考资料 ...
- Hadoop第12周练习—HBase安装部署
1 1.1 1.2 :安装HBase 2.1 内容 运行环境说明 1.1 硬软件环境 线程,主频2.2G,6G内存 l 虚拟软件:VMware® Workstation 9.0.0 build-8 ...
- 4、总结:基于Oracle Logminer数据同步
最近开发Oracle数据同步功能,做了些调研和验证,这个工作过去有段时间,怕时间长了忘记,故用博客共享出来.在这系列中共写了三篇文章,第一篇是写LogMiner配置及使用,第二篇是测试了LogMine ...
- python进阶学习笔记(四)--多线程thread
在使用多线程之前,我们首页要理解什么是进程和线程. 什么是进程? 计算机程序只不过是磁盘中可执行的,二进制(或其它类型)的数据.它们只有在被读取到内存中,被操作系统调用的时候才开始它们的生命期.进程( ...
- E:无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系
安装terminator等一些软件等时候,遇到了这样等问题 leo@leo:~$ sudo apt-get install terminator [sudo] password for leo: 正在 ...