程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> Automapper擴展方法,automapper擴展

Automapper擴展方法,automapper擴展

編輯:C#入門知識

Automapper擴展方法,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提高性能。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved