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提高性能。

你可能感兴趣的:(mapper)