AutoMaper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApplication4
{
    public class AutoMapper
    {
        public delegate string FormatColumnName(string columnName);

        /// <summary>
        /// 从缓存中取出对象的公共属性,用来解决反射的性能问题
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static PropertyInfo[] GetProperties<T>() where T : class
        {
            Type t = typeof(T);
            string key = string.Format("GetProperties_{0}", t.FullName);
            System.Runtime.Caching.MemoryCache cache = System.Runtime.Caching.MemoryCache.Default;
            if (cache[key] == null)
            {
                PropertyInfo[] properties = t.GetProperties();
                cache.Add(key, properties, new DateTimeOffset(DateTime.Now.AddMinutes(20)));
                return properties;
            }
            return cache[key] as PropertyInfo[];
        }
        public static List<string> GetColumnNames(IDataReader dr)
        {
            return GetColumnNames(dr, null);
        }
        public static List<string> GetColumnNames(IDataReader dr, FormatColumnName method)
        {
            List<string> list = new List<string>();
            for (int i = 0; i < dr.FieldCount; i++)
            {
                var fileName = dr.GetName(i);
                if (method != null)
                {
                    fileName = method(fileName);
                }
                list.Add(fileName);
            }
            return list;
        }
        /// <summary>
        /// 将数据库中的字段名用Pascel命名法则转换成类型的属性名,若有"_"则在"_"处将数据库字段名切割成N个片段,每个片段的首字母大写其余字母小写,将这些片段连接起来组成某个类的属性名
        /// </summary>
        /// <param name="columnName">columnName名</param>
        /// <returns></returns>
        private static string ConvertToPascal(string columnName)
        {
            string[] strArr = columnName.Split('_');
            StringBuilder result = new StringBuilder();
            foreach (string item in strArr)
            {
                if (item.Length > 0)
                {
                    result.Append(item.Substring(0, 1).ToUpper());
                    if (item.Length > 1)
                    {
                        result.Append(item.Substring(1).ToLower());
                    }
                }
            }
            return result.ToString();
        }
        /// <summary>
        /// 将数据库中的字段名用Pascel命名法则转换成类型的属性名,若有"_"则在"_"处将数据库字段名切割成N个片段,每个片段的首字母大写其余字母小写,将这些片段连接起来组成某个类的属性名
        /// </summary>
        public static readonly FormatColumnName ConvertToPascal2
            = columnName =>
            {
                string[] sArr = columnName.Split('_');
                StringBuilder result = new StringBuilder();
                foreach (string item in sArr)
                {
                    if (item.Length > 0)
                    {
                        result.Append(item.Substring(0, 1).ToUpper());
                        if (item.Length > 1)
                        {
                            result.Append(item.Substring(1).ToLower());
                        }
                    }
                }
                return result.ToString();
            };

        /// <summary>
        /// 将DataReader转换为实体集合
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dr">数据读取流</param>
        /// <param name="method">DataReader的字段名与类型T的属性名之间的转换函数</param>
        /// <returns></returns>
        public static List<T> DataReaderToModelList<T>(IDataReader dr, FormatColumnName method) where T : class, new()
        {
            List<T> list = null;
            var fieldNames = GetColumnNames(dr, method);
            var properties = GetProperties<T>();

            while (dr.Read())
            {
                if (list == null)
                {
                    list = new List<T>();
                }

                T o = new T();
                foreach (var p in properties)
                {
                    var columnName = p.Name;
                    if (fieldNames.Contains(columnName))
                    {
                        if (!Convert.IsDBNull(dr[columnName]))
                        {
                            object value = dr[columnName];
                            if (value.GetType() != p.PropertyType)
                            {
                                //如果dr中字段的类型与实体T的属性类型不匹配,则以T的属性类型为准
                                value = Convert.ChangeType(value, p.PropertyType);
                            }
                            p.SetValue(o, value, null);
                        }
                    }
                }
                list.Add(o);
            }
            return list;
        }

        /// <summary>
        /// 将DataReader转换成类型T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr">DataReader</param>
        /// <param name="method">DataReader的字段名与类型T的属性名之间的转换方法,FieldToPropertyMethods类中有几个预定义的静态方法可供使用</param>
        /// <returns></returns>
        public static T DataReaderToModel<T>(IDataReader dr) where T : class,new()
        {
            T objectInstance = new T();
            PropertyInfo[] properties = GetProperties<T>();
            var filedNames = GetColumnNames(dr);

            foreach (var p in properties)
            {
                var columnName = p.Name;
                if (filedNames.Contains(columnName))
                {
                    if (!Convert.IsDBNull(dr[columnName]))
                    {
                        object value = dr[columnName];
                        if (value.GetType() != p.PropertyType)
                        {
                            //如果dr中字段的类型与实体T的属性类型不匹配,则以T的属性类型为准
                            value = Convert.ChangeType(value, p.PropertyType);
                        }
                        p.SetValue(objectInstance, value, null);
                    }
                }
                
            }
            return objectInstance;
        }

        public static DbType GetDbType(object o)
        {
            string typeName = o.GetType().Name.ToLower();
            DbType dbType;
            switch (typeName)
            {
                case "guid":
                    dbType = DbType.Guid;
                    break;
                case "short":
                    dbType = DbType.Int16;
                    break;
                case "byte":
                    dbType = DbType.Byte;
                    break;
                case "int":
                    dbType = DbType.Int32;
                    break;
                case "long":
                    dbType = DbType.Int64;
                    break;
                case "dateTime":
                    dbType = DbType.DateTime;
                    break;
                case "double":
                    dbType = DbType.Double;
                    break;
                case "decimal":
                    dbType = DbType.Decimal;
                    break;
                case "float":
                    dbType = DbType.Decimal;
                    break;
                case "bool":
                    dbType = DbType.Boolean;
                    break;
                default:
                    dbType = DbType.String;
                    break;
            }
            return dbType;
        }

        public static DbType GetDbType2(Type type)
        {
            TypeCode typeCode = Type.GetTypeCode(type);
            DbType dt;
            switch (typeCode)
            {
                case TypeCode.Boolean:
                    dt = DbType.Boolean;
                    break;
                case TypeCode.Byte:
                    dt = DbType.Byte;
                    break;
                case TypeCode.Char:
                    dt = DbType.UInt16;
                    break;
                case TypeCode.DateTime:
                    dt = DbType.DateTime;
                    break;
                case TypeCode.Decimal:
                    dt = DbType.Decimal;
                    break;
                case TypeCode.Double:
                    dt = DbType.Double;
                    break;
                case TypeCode.Int16:
                    dt = DbType.Int16;
                    break;
                case TypeCode.Int32:
                    dt = DbType.Int32;
                    break;
                case TypeCode.Int64:
                    dt = DbType.Int64;
                    break;
                //case TypeCode.Object:
                //    dt = DbType.Object;
                //    break;
                case TypeCode.SByte:
                    dt = DbType.SByte;
                    break;
                case TypeCode.Single:
                    dt = DbType.Single;
                    break;
                case TypeCode.String:
                    dt = DbType.String;
                    break;
                case TypeCode.UInt16:
                    dt = DbType.UInt16;
                    break;
                case TypeCode.UInt32:
                    dt = DbType.UInt32;
                    break;
                case TypeCode.UInt64:
                    dt = DbType.UInt64;
                    break;
                default:
                    dt = DbType.Int32;
                    break;
            }
            return dt;
        }


        public SqlParameter[] SqlParameter<T>(T entity) where T:class, new()
        {
            IList<SqlParameter> sqlParameterList = new List<SqlParameter>();
            PropertyInfo[] properties = GetProperties<T>();
            foreach (var p in properties)
            {
                SqlParameter sqlParameter = new SqlParameter();
                sqlParameter.ParameterName = string.Format("@{0}", p.Name);
                sqlParameter.Value = p.GetValue(entity, null);
                sqlParameter.DbType = GetDbType(p.PropertyType);
                sqlParameterList.Add(sqlParameter);
            }
            return sqlParameterList.ToArray();
        }

        /// <summary>
        /// 将DataReader转换为泛型集合
        /// </summary>
        /// <typeparam naame="T">泛型</typeparam>
        /// <param name="dr">DataReader</param>
        /// <returns></returns>
        private List<T> DataReaderToEntityList<T>(IDataReader dr) where T : class
        {
            List<T> list = new List<T>();
            Type t = typeof(T);
            PropertyInfo[] properties = t.GetProperties();
            while (dr.Read())
            {
                T o = Activator.CreateInstance(t) as T;
                foreach (PropertyInfo p in properties)
                {
                    if (!Convert.IsDBNull(dr[p.Name]))
                    {
                        p.SetValue(o, dr[p.Name], null);
                    }
                }
                T e = o as T;
                list.Add(e);
            }
            return list;
        }
        private List<T> DataReaderToEntityList2<T>(IDataReader dr) where T : class, new()
        {
            List<T> result = new List<T>();
            PropertyInfo[] properties = GetProperties<T>();
            List<string> fieldNames = GetColumnNames(dr);
            while (dr.Read())
            {
                T objectInstance = new T();
                foreach (var p in properties)
                {
                    var exists = fieldNames.Exists(item => item.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
                    if (exists)
                    {
                        p.SetValue(objectInstance, dr[p.Name], null);
                    }
                }
                result.Add(objectInstance);
            }
            return result;

        }
        private T DataReaderToEntity<T>(IDataReader dr) where T : class, new()
        {
            T objectInstance = new T();
            PropertyInfo[] properties = GetProperties<T>();
            for (int i = 0; i < dr.FieldCount; i++)
            {
                foreach (var p in properties)
                {
                    if (p.Name == dr.GetName(i))
                    {
                        p.SetValue(objectInstance, dr[i], null);
                    }
                }
            }
            return objectInstance;
        }
        /// <summary>
        /// 映射
        /// </summary>
        /// <typeparam name="FormT">源类型</typeparam>
        /// <typeparam name="ToT">目标类型</typeparam>
        /// <param name="formObject">源对象</param>
        /// <returns>目标对象</returns>
        public static ToT Mapping<FormT, ToT>(FormT formObject)
            where FormT : class, new()
            where ToT : class, new()
        {
            //http://blog.csdn.net/cxzhq2002/article/details/8753495
            //集合到集合暂没有实现
            ToT t = new ToT();
            PropertyInfo[] formProperties = GetProperties<FormT>();
            PropertyInfo[] toProperties = GetProperties<ToT>();
            foreach (var p in toProperties)
            {
                var exists = formProperties.Where(item => item.Name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
                if (exists.Count() > 0)
                {
                    var value = exists.First().GetValue(formObject, null);
                    p.SetValue(t, value, null);
                }
            }
            return t;
        }

        public static IList<V> Mapping<U, V>(IList<U> formList)
            where U : class, new()
            where V : class, new()
        {
            //http://blog.csdn.net/cxzhq2002/article/details/8753495
            //集合到集合暂没有实现

             //轻量的映射工具,不可与ORM做比较。它不参与到DB。一般用来配合SqlHelper/企业库来使用
            //作用:1.参数;2.dataReader转为Entity或List,3.对象对象,集合到集合,不支持深嵌套对象。

            PropertyInfo[] formProperties = GetProperties<U>();
            PropertyInfo[] toProperties = GetProperties<V>();

            IList<V> toList = new List<V>();
            foreach (var item in formList)
            {
                V to = new V();
                foreach (var p in toProperties)
                {
                    var exists = formProperties.Where(k => k.Name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
                    if (exists.Count() > 0)
                    {
                        var value = exists.First().GetValue(item, null);
                        p.SetValue(to, value, null);
                    }
                }
                toList.Add(to);                
            }
            return toList;
        }
        /// <summary>
        /// 映射
        /// </summary>
        /// <typeparam name="FormT">源类型</typeparam>
        /// <typeparam name="ToT">目标类型</typeparam>
        /// <param name="formObject">源对象</param>
        /// <returns>目标对象</returns>
        public static void Mapping<FormT, ToT>(FormT formObject, ToT toObject)
            where FormT : class, new()
            where ToT : class, new()
        {
            PropertyInfo[] formProperties = GetProperties<FormT>();
            PropertyInfo[] toProperties = GetProperties<ToT>();
            foreach (var p in toProperties)
            {
                var index = formProperties.ToList().FindIndex(item => item.Name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
                if (index >= 0)
                {
                    var value = formProperties[index].GetValue(formObject, null);
                    p.SetValue(toObject, value, null);
                }
            }
        }
    }
}


//轻量的映射工具,不可与ORM做比较。它不参与到DB。一般用来配合SqlHelper/企业库来使用
//作用:1.参数;2.dataReader转为Entity或List,3.对象对象,集合到集合,不支持深嵌套对象。

数据库部分参数可借助dynamic来实现必须要的参数(暂时没办法添加值类型) 

            dynamic student = new { Name = "张三", Gender = true, Age = 25, Birthday = DateTime.Now };
            Console.Write(student.GetType());
 增加Attibute来实现特殊对映

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值