///// <summary>
        ///// Create entity(model) object by IDataReader.
        ///// </summary>
        ///// <typeparam name="T">Type of Entity(Model)</typeparam>
        ///// <param name="dr">Related datereader</param>
        ///// <remarks>Please make sure the Fields Name of Entity(Model)
        ///// and input daterader are same.</remarks>
        ///// <returns>Object of Entity(Model)</returns>
        //public static T CreateModel<T>(IDataReader dr, bool checkColumn)
        //{
        //    if (dr.Read())
        //    {

        //        if (!TypeCache.Keys.Contains(typeof(T)))
        //        {
        //            lock (syncRoot)
        //            {
        //                if (!TypeCache.Keys.Contains(typeof(T)))
        //                {
        //                    TypeCache.Add(typeof(T), EmitHelper.GetInstanceCreator(typeof(T)));
        //                }
        //            }
        //        }

        //        T obj = (T)TypeCache[typeof(T)].Invoke();

        //        foreach (PropertyInfo p in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        //        {
        //            if (!PropCache.Keys.Contains(p))
        //            {
        //                lock (syncRoot)
        //                {
        //                    if (!PropCache.Keys.Contains(p) && p.CanWrite)
        //                    {
        //                        PropCache.Add(p, EmitHelper.GetPropertySetter(p));
        //                    }
        //                }
        //            }
        //            if (readerExists(dr, p.Name))
        //            {
        //                PropCache[p](obj, ChangeType(dr[p.Name], p.PropertyType));
        //            }
        //        }

        //        return obj;

        //    }
        //    else
        //    {
        //        return default(T);
        //    }
        //}
        /// <summary>
        /// Create entity(model) object by IDataReader.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <param name="checkColumn"></param>
        /// <returns></returns>
        public static T CreateModel <T>(IDataReader dr, bool checkColumn)
        {
            Type type = typeof(T);

            if (!DTOTypeCache.ContainKeys(type))
            {
                lock (syncRoot)
                {
                    if (!DTOTypeCache.ContainKeys(type))
                    {
                        DTOTypeCache.Add(type, EmitHelper.GetInstanceCreator(type));
                    }
                }
            }

            var columns = GetColumns(dr);
            var dtoType = DTOTypeCache.GetDTOType(type);

            if (dr.Read())
            {
                var propertyInfos = dtoType.Properties.Count > 0 && dtoType.Properties.Count >= columns.Count ? dtoType.Properties.Select(o => o.Value.Info).ToArray() : type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

                T obj = (T)dtoType.Handler.Invoke();

                foreach (PropertyInfo p in propertyInfos)
                {
                    if (!HasColumn(columns, p.Name))
                    {
                        continue;
                    }

                    if (p.CanWrite && !dtoType.Properties.ContainsKey(p.Name))
                    {
                        lock (syncRoot)
                        {
                            if (p.CanWrite && !dtoType.Properties.ContainsKey(p.Name))
                            {
                                dtoType.Properties.Add(p.Name, new DTOProperty(p, EmitHelper.GetPropertySetter(p)));
                            }
                        }
                    }
                    if (!p.CanWrite)
                    {
                        continue;
                    }

                    dtoType.Properties[p.Name].Handler(obj, ChangeType(dr[p.Name], p.PropertyType));
                }

                return(obj);
            }
            else
            {
                return(default(T));
            }
        }
        ///// <summary>
        ///// Create entity(model) object list by IDataReader.
        ///// </summary>
        ///// <typeparam name="T">Type of Entity(Model)</typeparam>
        ///// <param name="dr">Related datereader</param>
        ///// <remarks>Please make sure the Fields Name of Entity(Model)
        ///// and input daterader are same.</remarks>
        ///// <returns>Object list of Entity(Model)</returns>
        //public static List<T> CreateModelList<T>(IDataReader dr)
        //{
        //    List<T> list = new List<T>();
        //    T obj;

        //    if (!TypeCache.Keys.Contains(typeof(T)))
        //    {
        //        lock (syncRoot)
        //        {
        //            if (!TypeCache.Keys.Contains(typeof(T)))
        //            {
        //                TypeCache.Add(typeof(T), EmitHelper.GetInstanceCreator(typeof(T)));
        //            }
        //        }
        //    }

        //    DataTable dcc = dr.GetSchemaTable();

        //    while (dr.Read())
        //    {
        //        obj = (T)TypeCache[typeof(T)].Invoke();

        //        foreach (PropertyInfo p in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        //        {
        //            if (!HasColumn(dcc, p.Name))
        //                continue;

        //            if (!PropCache.Keys.Contains(p))
        //            {
        //                lock (syncRoot)
        //                {
        //                    if (!PropCache.Keys.Contains(p))
        //                    {
        //                        PropCache.Add(p, EmitHelper.GetPropertySetter(p));
        //                    }
        //                }
        //            }

        //            if (p.PropertyType.IsEnum)
        //            {
        //                PropCache[p](obj, ChangeType(dr[p.Name], typeof(int)));
        //            }
        //            else
        //                PropCache[p](obj, ChangeType(dr[p.Name], p.PropertyType));
        //        }

        //        list.Add(obj);

        //    }

        //    return list;
        //}
        /// <summary>
        /// Create entity(model) object list by IDataReader. 已优化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static List <T> CreateModelList <T>(IDataReader dr)
        {
            List <T> list = new List <T>();
            T        obj;

            Type type = typeof(T);

            //if (!DTOTypeCache.ContainKeys(type))
            //{
            //    lock (syncRoot)
            //    {
            //        if (!DTOTypeCache.ContainKeys(type))
            //        {
            //            DTOTypeCache.Add(type, EmitHelper.GetInstanceCreator(type));
            //        }
            //    }
            //}
            if (!DTOTypeCache.ContainKeys(type))
            {
                lock (syncRoot)
                {
                    if (!DTOTypeCache.ContainKeys(type))
                    {
                        DTOTypeCache.Add(type, EmitHelper.GetInstanceCreator(type));
                    }
                }
            }
            //数据库得到的列名
            var  columns      = GetColumns(dr);
            var  dtoType      = DTOTypeCache.GetDTOType(type);
            bool loadProperty = false;
            bool loadFinished = false;
            IEnumerable <PropertyInfo> propertyInfos = null;

            while (dr.Read())
            {
                if (propertyInfos == null || loadProperty)
                {
                    loadProperty  = false;
                    propertyInfos = dtoType.Properties.Count > 0 && dtoType.Properties.Count >= columns.Count ? dtoType.Properties.Select(o => o.Value.Info).ToArray() : type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                    //  propertyInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                }

                obj = (T)dtoType.Handler.Invoke();
                foreach (PropertyInfo p in propertyInfos)
                {
                    if (!loadFinished && !dtoType.Properties.ContainsKey(p.Name))
                    {
                        lock (syncRoot)
                        {
                            if (p.CanWrite && !dtoType.Properties.ContainsKey(p.Name))
                            {
                                dtoType.Properties.Add(p.Name, new DTOProperty(p, EmitHelper.GetPropertySetter(p)));
                                loadProperty = true;
                            }
                        }
                    }
                    if (!HasColumn(columns, p.Name) || !p.CanWrite)
                    {
                        continue; //属性不在返回的列中
                    }
                    var changedValue = ChangeType(dr[p.Name], p.PropertyType);
                    var py           = dtoType.Properties[p.Name];
                    py.Handler(obj, changedValue);
                }

                list.Add(obj);
                loadFinished = true;
            }

            return(list);
        }