using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Reflection; /// <summary>
/// 实体阅读器类,可以从DataTable中或者DbDataReader的实例中将数据转换成对应的示例
/// 作者:周公
/// 日期:2011-07-17
/// 修改日期:2011-07-21
/// 博客地址:http://blog.csdn.net/zhoufoxcn 或http://zhoufoxcn.blog.51cto.com
/// 说明:(1)任何人都可以免费使用,请尽量保持此段说明。
/// (2)这个版本还不是最终版本,有任何意见或建议请到http://weibo.com/zhoufoxcn处留言。
/// </summary>
public sealed class EntityReader
{
private const BindingFlags BindingFlag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
//将类型与该类型所有的可写且未被忽略属性之间建立映射
private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyMappings = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
//存储Nullable<T>与T的对应关系
private static Dictionary<Type, Type> genericTypeMappings = new Dictionary<Type, Type>(); static EntityReader()
{
genericTypeMappings.Add(typeof(Byte?), typeof(Byte));
genericTypeMappings.Add(typeof(SByte?), typeof(SByte));
genericTypeMappings.Add(typeof(Char?), typeof(Char));
genericTypeMappings.Add(typeof(Boolean?), typeof(Boolean));
genericTypeMappings.Add(typeof(Guid?), typeof(Guid));
genericTypeMappings.Add(typeof(Int16), typeof(Int16));
genericTypeMappings.Add(typeof(UInt16), typeof(UInt16));
genericTypeMappings.Add(typeof(Int32), typeof(Int32));
genericTypeMappings.Add(typeof(UInt32), typeof(UInt32));
genericTypeMappings.Add(typeof(Int64), typeof(Int64));
genericTypeMappings.Add(typeof(UInt64), typeof(UInt64));
genericTypeMappings.Add(typeof(Single), typeof(Single));
genericTypeMappings.Add(typeof(Double), typeof(Double));
genericTypeMappings.Add(typeof(Decimal), typeof(Decimal));
genericTypeMappings.Add(typeof(DateTime), typeof(DateTime));
genericTypeMappings.Add(typeof(TimeSpan), typeof(TimeSpan));
genericTypeMappings.Add(typeof(Enum), typeof(Enum)); }
/// <summary>
/// 将DataTable中的所有数据转换成List&gt;T&lt;集合
/// </summary>
/// <typeparam name="T">DataTable中每条数据可以转换的数据类型</typeparam>
/// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
/// <returns></returns>
public static List<T> GetEntities<T>(DataTable dataTable) where T : new()
{
if (dataTable == null)
{
throw new ArgumentNullException("dataTable");
}
//如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
if(typeof(T)==typeof(string)||typeof(T).IsValueType)
{
return GetSimpleEntities<T>(dataTable);
}
else
{
return GetComplexEntities<T>(dataTable);
}
}
/// <summary>
/// 将DbDataReader中的所有数据转换成List&gt;T&lt;集合
/// </summary>
/// <typeparam name="T">DbDataReader中每条数据可以转换的数据类型</typeparam>
/// <param name="dataTable">包含有可以转换成数据类型T的DbDataReader实例</param>
/// <returns></returns>
public static List<T> GetEntities<T>(DbDataReader reader) where T : new()
{
List<T> list = new List<T>();
if (reader == null)
{
throw new ArgumentNullException("reader");
}
//如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
if (typeof(T) == typeof(string) || typeof(T).IsValueType)
{
return GetSimpleEntities<T>(reader);
}
else
{
return GetComplexEntities<T>(reader);
} }
/// <summary>
/// 从DataTable中将每一行的第一列转换成T类型的数据
/// </summary>
/// <typeparam name="T">要转换的目标数据类型</typeparam>
/// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
/// <returns></returns>
private static List<T> GetSimpleEntities<T>(DataTable dataTable) where T : new()
{
List<T> list = new List<T>();
foreach (DataRow row in dataTable.Rows)
{
list.Add((T)GetValueFromObject(row[], typeof(T)));
}
return list;
}
/// <summary>
/// 将指定的 Object 的值转换为指定类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <param name="targetType">要转换的目标数据类型</param>
/// <returns></returns>
private static object GetValueFromObject(object value, Type targetType)
{
if (targetType == typeof(string))//如果要将value转换成string类型
{
return GetString(value);
}
else if (targetType.IsGenericType)//如果目标类型是泛型
{
return GetGenericValueFromObject(value, targetType);
}
else//如果是基本数据类型(包括数值类型、枚举和Guid)
{
return GetNonGenericValueFromObject(value, targetType);
}
} /// <summary>
/// 从DataTable中读取复杂数据类型集合
/// </summary>
/// <typeparam name="T">要转换的目标数据类型</typeparam>
/// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
/// <returns></returns>
private static List<T> GetComplexEntities<T>(DataTable dataTable) where T : new()
{
if (!propertyMappings.ContainsKey(typeof(T)))
{
GenerateTypePropertyMapping(typeof(T));
}
List<T> list = new List<T>();
Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
//Dictionary<string, int> propertyColumnOrdinalMapping = GetPropertyColumnIndexMapping(dataTable.Columns, properties);
T t;
foreach (DataRow row in dataTable.Rows)
{
t = new T();
foreach (KeyValuePair<string, PropertyInfo> item in properties)
{
//int ordinal = -1;
//if (propertyColumnOrdinalMapping.TryGetValue(item.Key, out ordinal))
//{
// item.Value.SetValue(t, GetValueFromObject(row[ordinal], item.Value.PropertyType), null);
//}
item.Value.SetValue(t, GetValueFromObject(row[item.Key], item.Value.PropertyType), null);
}
list.Add(t);
}
return list;
} /// <summary>
/// 从DbDataReader的实例中读取复杂的数据类型
/// </summary>
/// <typeparam name="T">要转换的目标类</typeparam>
/// <param name="reader">DbDataReader的实例</param>
/// <returns></returns>
private static List<T> GetComplexEntities<T>(DbDataReader reader) where T : new()
{
if (!propertyMappings.ContainsKey(typeof(T)))//检查当前是否已经有该类与类的可写属性之间的映射
{
GenerateTypePropertyMapping(typeof(T));
}
List<T> list = new List<T>();
Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
//Dictionary<string, int> propertyColumnOrdinalMapping = GetPropertyColumnIndexMapping(reader, properties);
T t;
while (reader.Read())
{
t = new T();
foreach (KeyValuePair<string, PropertyInfo> item in properties)
{
//int ordinal = -1;
//if (propertyColumnOrdinalMapping.TryGetValue(item.Key, out ordinal))
//{
// item.Value.SetValue(t, GetValueFromObject(reader[ordinal], item.Value.PropertyType), null);
//}
item.Value.SetValue(t, GetValueFromObject(reader[item.Key], item.Value.PropertyType), null);
}
list.Add(t);
}
return list;
}
/// <summary>
/// 从DbDataReader的实例中读取简单数据类型(String,ValueType)
/// </summary>
/// <typeparam name="T">目标数据类型</typeparam>
/// <param name="reader">DbDataReader的实例</param>
/// <returns></returns>
private static List<T> GetSimpleEntities<T>(DbDataReader reader)
{
List<T> list = new List<T>();
while (reader.Read())
{
list.Add((T)GetValueFromObject(reader[], typeof(T)));
}
return list;
}
/// <summary>
/// 将Object转换成字符串类型
/// </summary>
/// <param name="value">object类型的实例</param>
/// <returns></returns>
private static object GetString(object value)
{
return Convert.ToString(value);
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <param name="targetType"></param>
/// <returns></returns>
private static object GetEnum(object value, Type targetType)
{
return Enum.Parse(targetType, value.ToString());
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetBoolean(object value)
{
if (value is Boolean)
{
return value;
}
else
{
byte byteValue = (byte)GetByte(value);
if (byteValue == )
{
return false;
}
else
{
return true;
}
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetByte(object value)
{
if (value is Byte)
{
return value;
}
else
{
return byte.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetSByte(object value)
{
if (value is SByte)
{
return value;
}
else
{
return SByte.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetChar(object value)
{
if (value is Char)
{
return value;
}
else
{
return Char.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetGuid(object value)
{
if (value is Guid)
{
return value;
}
else
{
return new Guid(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetInt16(object value)
{
if (value is Int16)
{
return value;
}
else
{
return Int16.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetUInt16(object value)
{
if (value is UInt16)
{
return value;
}
else
{
return UInt16.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetInt32(object value)
{
if (value is Int32)
{
return value;
}
else
{
return Int32.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetUInt32(object value)
{
if (value is UInt32)
{
return value;
}
else
{
return UInt32.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetInt64(object value)
{
if (value is Int64)
{
return value;
}
else
{
return Int64.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetUInt64(object value)
{
if (value is UInt64)
{
return value;
}
else
{
return UInt64.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetSingle(object value)
{
if (value is Single)
{
return value;
}
else
{
return Single.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetDouble(object value)
{
if (value is Double)
{
return value;
}
else
{
return Double.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetDecimal(object value)
{
if (value is Decimal)
{
return value;
}
else
{
return Decimal.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetDateTime(object value)
{
if (value is DateTime)
{
return value;
}
else
{
return DateTime.Parse(value.ToString());
}
} /// <summary>
/// 将指定的 Object 的值转换为指定枚举类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <returns></returns>
private static object GetTimeSpan(object value)
{
if (value is TimeSpan)
{
return value;
}
else
{
return TimeSpan.Parse(value.ToString());
}
} /// <summary>
/// 将Object类型数据转换成对应的可空数值类型表示
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <param name="targetType">可空数值类型</param>
/// <returns></returns>
private static object GetGenericValueFromObject(object value,Type targetType)
{
if (value == DBNull.Value)
{
return null;
}
else
{
//获取可空数值类型对应的基本数值类型,如int?->int,long?->long
Type nonGenericType= genericTypeMappings[targetType];
return GetNonGenericValueFromObject(value, nonGenericType);
}
} /// <summary>
/// 将指定的 Object 的值转换为指定类型的值。
/// </summary>
/// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
/// <param name="targetType">目标对象的类型</param>
/// <returns></returns>
private static object GetNonGenericValueFromObject(object value, Type targetType)
{
if (targetType.IsEnum)//因为
{
return GetEnum(value, targetType);
}
else
{
switch (targetType.Name)
{
case "Byte": return GetByte(value);
case "SByte": return GetSByte(value);
case "Char": return GetChar(value);
case "Boolean": return GetBoolean(value);
case "Guid": return GetGuid(value);
case "Int16": return GetInt16(value) ;
case "UInt16": return GetUInt16(value);
case "Int32": return GetInt32(value);
case "UInt32": return GetUInt32(value);
case "Int64": return GetInt64(value);
case "UInt64": return GetUInt64(value);
case "Single": return GetSingle(value);
case "Double": return GetDouble(value);
case "Decimal": return GetDecimal(value);
case "DateTime": return GetDateTime(value);
case "TimeSpan": return GetTimeSpan(value);
default: return null;
}
}
} /// <summary>
/// 获取该类型中属性与数据库字段的对应关系映射
/// </summary>
/// <param name="type"></param>
private static void GenerateTypePropertyMapping(Type type)
{
if (type != null)
{
PropertyInfo[] properties = type.GetProperties(BindingFlag);
Dictionary<string, PropertyInfo> propertyColumnMapping = new Dictionary<string, PropertyInfo>(properties.Length);
string description = string.Empty;
Attribute[] attibutes = null;
string columnName = string.Empty;
bool ignorable = false;
foreach (PropertyInfo p in properties)
{
ignorable = false;
columnName = string.Empty;
attibutes = Attribute.GetCustomAttributes(p);
foreach (Attribute attribute in attibutes)
{
//检查是否设置了ColumnName属性
if (attribute.GetType() == typeof(ColumnNameAttribute))
{
columnName = ((ColumnNameAttribute)attribute).ColumnName;
ignorable = ((ColumnNameAttribute)attribute).Ignorable;
break;
}
}
//如果该属性是可读并且未被忽略的,则有可能在实例化该属性对应的类时用得上
if (p.CanWrite&&!ignorable)
{
//如果没有设置ColumnName属性,则直接将该属性名作为数据库字段的映射
if (string.IsNullOrEmpty(columnName))
{
columnName = p.Name;
}
propertyColumnMapping.Add(columnName, p);
}
}
propertyMappings.Add(type, propertyColumnMapping);
}
} //private static Dictionary<string, int> GetPropertyColumnIndexMapping(DataColumnCollection dataSource, Dictionary<string, PropertyInfo> properties)
//{
// Stopwatch watch = new Stopwatch();
// watch.Start();
// Dictionary<string,int> propertyColumnIndexMapping=new Dictionary<string,int>(dataSource.Count);
// foreach(KeyValuePair<string,PropertyInfo> item in properties)
// {
// for (int i = 0; i < dataSource.Count; i++)
// {
// if (item.Key.Equals(dataSource[i].ColumnName, StringComparison.InvariantCultureIgnoreCase))
// {
// propertyColumnIndexMapping.Add(item.Key, i);
// break;
// }
// }
// }
// watch.Stop();
// Debug.WriteLine("Elapsed:" + watch.ElapsedMilliseconds);
// return propertyColumnIndexMapping;
//} //private static Dictionary<string, int> GetPropertyColumnIndexMapping(DbDataReader dataSource, Dictionary<string, PropertyInfo> properties)
//{
// Dictionary<string, int> propertyColumnIndexMapping = new Dictionary<string, int>(dataSource.FieldCount);
// foreach (KeyValuePair<string, PropertyInfo> item in properties)
// {
// for (int i = 0; i < dataSource.FieldCount; i++)
// {
// if (item.Key.Equals(dataSource.GetName(i), StringComparison.InvariantCultureIgnoreCase))
// {
// propertyColumnIndexMapping.Add(item.Key, i);
// continue;
// }
// }
// }
// return propertyColumnIndexMapping;
//}
}
/// <summary>
/// 自定义属性,用于指示如何从DataTable或者DbDataReader中读取类的属性值
/// </summary>
public class ColumnNameAttribute : Attribute
{
/// <summary>
/// 类属性对应的列名
/// </summary>
public string ColumnName { get; set; }
/// <summary>
/// 指示在从DataTable或者DbDataReader中读取类的属性时是否可以忽略这个属性
/// </summary>
public bool Ignorable { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="columnName">类属性对应的列名</param>
public ColumnNameAttribute(string columnName)
{
ColumnName = columnName;
Ignorable = false;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ignorable">指示在从DataTable或者DbDataReader中读取类的属性时是否可以忽略这个属性</param>
public ColumnNameAttribute(bool ignorable)
{
Ignorable = ignorable;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="columnName">类属性对应的列名</param>
/// <param name="ignorable">指示在从DataTable或者DbDataReader中读取类的属性时是否可以忽略这个属性</param>
public ColumnNameAttribute(string columnName, bool ignorable)
{
ColumnName = columnName;
Ignorable = ignorable;
}
}

C#实体转换的更多相关文章

  1. DataTable转List<Model>通用类【实体转换辅助类】

    /// <summary> /// DataTable转List<Model>通用类[实体转换辅助类] /// </summary> public class Mo ...

  2. HBaseConvetorUtil 实体转换工具

    HBaseConvetorUtil 实体转换工具类 public class HBaseConvetorUtil {        /**    * @Title: convetor    * @De ...

  3. Datatable转实体 实体转换辅助类

    using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.R ...

  4. html实体转换

    摘要: 在 HTML 中,某些字符是预留的.在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签.如果希望正确地显示预留字符,我们必须在 HTML 源代码中 ...

  5. C# 获取config文件 实体转换

    随着项目的扩展,单独的key,value配置文件已经不能满足需求了 这里需要自定义配置节点,例如 <!--自定义 具体实体类配置问节点信息--> <School Name=" ...

  6. C# 实体集合和实体转换成相应的string、XDocument、XElement、XDocument

    https://msdn.microsoft.com/zh-cn/library/system.xml.linq.xelement(v=vs.110).aspx XElement.Parse 方法 ( ...

  7. .NET 实体转换辅助类

    /// <summary> /// 实体转换辅助类 /// </summary> public class ModelConvertHelper<T> where ...

  8. C#中实体集合和实体转换成相应的string、XDocument、XElement

    C#中实体集合和实体转换成相应的string.XDocument.XElement public class SimpleXmlConverter { public static string ToX ...

  9. .Net Core2.2 使用 AutoMapper进行实体转换

    一.遇到的问题 在. Core Api 的编写中,我们经常会对一些功能点进行新增编辑操作,同时我们有时也会进行查询,但是我们查询的表的数据与我们返回的数据相差甚大,这是我们有需要自己手动进行类型的转换 ...

  10. mapstruct 实体转换及List转换,@Mapper注解转换

    本文参考 https://blog.csdn.net/u012373815/article/details/88367456 主要是为了自己使用方便查询. 这些都是我平时用到了,大家有什么好方法或者有 ...

随机推荐

  1. α&β测试的定义及结束的标准

    α测试在系统开发接近完成时对应用系统的测试:测试后仍然会有少量的设计变更.这种测试一般由最终用户或其他人员完成,不能由程序或测试员完成. β测试当开发和测试根本完成时所做的用例,最终的错误和问题需要在 ...

  2. ES6 arrow function

    语法: () => { … } // 零个参数用 () 表示: x => { … } // 一个参数可以省略 (): (x, y) => { … } // 多参数不能省略 (): 当 ...

  3. javascript跨域的几种方法

    以下的例子包含的文件均为为 http://www.a.com/a.html .http://www.a.com/c.html 与 http://www.b.com/b.html,要做的都是从a.htm ...

  4. PHP获取远程和本地文件信息(汇总)

    1.PHP filesize() 函数filesize() 函数返回指定文件的大小.若成功,则返回文件大小的字节数.若失败,则返回 false 并生成一条 E_WARNING 级的错误. 但是只能获取 ...

  5. VTK初始化New返回Null问题

    原文链接:http://www.cppblog.com/mythma/archive/2013/08/02/vtk-6-new-null.html 在使用VTK6.0时候,会遇到X::New()返回为 ...

  6. 请不要继续使用VC6.0了!

    很多次和身边的同学交流,帮助同学修改代码,互相分享经验,却发现同学们依然在使用老旧的VC6.0作为编程学习的软件,不由得喊出:“请不要继续使用VC6.0了!”. VC6.0作为当年最好的IDE(集成开 ...

  7. Node.js常用express方法

    Node.js 手册查询-Express 方法 1.send方法 send 方法向浏览器发送一个响应信息,并可以智能处理不同类型的数据 send方法在输出响应时会自动进行一些设置,比如HEAD信息.H ...

  8. Java---23种设计模式(九)------组合模式

    一.什么是组合模式 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象. 组合模式依据树形结构来组合对象,用来表示部分以及整体层次. 这种类型的 ...

  9. boost asio异步读写网络聊天程序客户端 实例详解

    boost官方文档中聊天程序实例讲解 数据包格式chat_message.hpp <pre name="code" class="cpp">< ...

  10. Django基础(二)

    Django基础(二) http://www.cnblogs.com/wupeiqi/articles/4508271.html