zoukankan      html  css  js  c++  java
  • 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提高性能。

  • 相关阅读:
    python接口测试(二)——配置文件的使用
    python接口测试(一)——http请求及token获取
    jmeter接口测试--响应结果Unicode转码成中文
    jmeter接口测试--获取token
    jmeter接口测试--参数化
    Sysbench安装步骤及详情
    云数据库安装及使用
    npm start 和 npm run start的关系
    使用JS控制伪元素的几种方法
    html5新属性
  • 原文地址:https://www.cnblogs.com/miku/p/4354550.html
Copyright © 2011-2022 走看看