关于C#中Array和DataTable间相互转换的说明

一、将Array转换为DataTable:

/// <summary>
/// 转换对象数组为数据表
/// </summary>
/// <param name="objs">对象数组</param>
/// <param name="members">需要转换的成员</param>
/// <param name="ignoreMembers">忽略转换的成员</param>
/// <returns>返回数据表</returns>
public virtual DataTable ConvertTable(object[] objs, string[] members, string[] ignoreMembers)
{
    // 创建目标数据表
    DataTable dataTable = new DataTable();
    // 获取对象数组元素类型
    Type type = objs.GetType().GetElementType();
    // 创建要转换的对象成员字典
    Dictionary<string, MemberInfo> memberInfos = new Dictionary<string, MemberInfo>();
    // 获取成员字段
    FieldInfo[] fieldInfos = type.GetFields();
    // 遍历成员字段,添加要转换的成员字段到字典中
    foreach (FieldInfo fieldInfo in fieldInfos)
    {
        // 获取当前字段名
        string name = fieldInfo.Name;
        // 判断当前字段是否需要转换
        if ((members == null || members.Length <= 0 || members.Contains("*") || members.Contains(name)) && (ignoreMembers == null || ignoreMembers.Length <= 0 || (!ignoreMembers.Contains("*") && !ignoreMembers.Contains(name))))
        {
            // 判断当前字段是否是公开的
            if (fieldInfo.IsPublic)
            {
                // 添加要转换的成员字段
                memberInfos[name] = fieldInfo;
            }
        }
    }
    // 获取成员属性
    PropertyInfo[] propertyInfos = type.GetProperties();
    // 遍历成员属性,添加要转换的成员属性到字典中
    foreach (PropertyInfo propertyInfo in propertyInfos)
    {
        // 获取当前属性名
        string name = propertyInfo.Name;
        // 判断当前属性是否需要转换
        if ((members == null || members.Length <= 0 || members.Contains("*") || members.Contains(name)) && (ignoreMembers == null || ignoreMembers.Length <= 0 || (!ignoreMembers.Contains("*") && !ignoreMembers.Contains(name))))
        {
            // 判断当前属性是否可读
            if (propertyInfo.CanRead)
            {
                // 获取当前属性的GET访问器
                MethodInfo methodInfo = propertyInfo.GetGetMethod();
                // 判断当前属性的GET访问器是否是公开的
                if (methodInfo.IsPublic)
                {
                    // 添加要转换的成员属性
                    memberInfos[name] = propertyInfo;
                }
            }
        }
    }
    // 遍历要转换的对象成员字典,添加数据列
    foreach (KeyValuePair<string, MemberInfo> item in memberInfos)
    {
        // 添加数据列
        DataColumn dataColumn = dataTable.Columns.Add(item.Key);
        // 定义数据列数据类型
        Type dataType = typeof(string);
        // 获取对象成员
        MemberInfo membeInfo = item.Value;
        // 判断对象成员是否是属性
        if (membeInfo is PropertyInfo)
        {
            // 获取成员属性
            PropertyInfo propertyInfo = membeInfo as PropertyInfo;
            // 设置数据列类型
            dataType = propertyInfo.PropertyType;
        }
        else
        {
            // 获取成员字段
            FieldInfo fieldInfo = membeInfo as FieldInfo;
            // 设置数据列类型
            dataType = fieldInfo.FieldType;
        }
        // 判断数据类型是否是可空的泛型值类型
        if (dataType.IsGenericType && dataType.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            // 取出可空泛型值类型中的基础值类型
            dataType = Nullable.GetUnderlyingType(dataType);
        }
        // 设置数据列数据类型
        dataColumn.DataType = dataType;
    }
    // 遍历对象数组,转换对象为数据行
    foreach (object obj in objs)
    {
        // 创建数据行数据链表
        List<object> values = new List<object>();
        // 遍历要转换的对象成员字典,转换成员数据
        foreach (KeyValuePair<string, MemberInfo> item in memberInfos)
        {
            // 定义成员数据
            object value = null;
            // 获取对象成员
            MemberInfo membeInfo = item.Value;
            // 判断对象成员是否是属性
            if (membeInfo is PropertyInfo)
            {
                // 获取成员属性
                PropertyInfo propertyInfo = membeInfo as PropertyInfo;
                // 获取当前成员属性的GET访问器
                MethodInfo methodInfo = propertyInfo.GetGetMethod();
                // 判断当前成员属性的GET访问器是否是静态的
                if (methodInfo.IsStatic)
                {
                    // 获取成员属性的静态值
                    value = propertyInfo.GetValue(null, null);
                }
                else
                {
                    // 获取成员属性的实例值
                    value = propertyInfo.GetValue(obj, null);
                }
            }
            else
            {
                // 获取成员字段
                FieldInfo fieldInfo = membeInfo as FieldInfo;
                // 判断当前成员字段是否是静态的
                if (fieldInfo.IsStatic)
                {
                    // 获取成员字段的静态值
                    value = fieldInfo.GetValue(null);
                }
                else
                {
                    // 获取成员字段的实例值
                    value = fieldInfo.GetValue(obj);
                }
            }
            // 添加成员数据到数据行数据链表中
            values.Add(value);
        }
        // 添加数据行
        dataTable.Rows.Add(values.ToArray());
    }
    // 返回数据表
    return dataTable;
}

二、将DataTable转换为Array:

/// <summary>
/// 转换数据表为对象数组
/// </summary>
/// <param name="type">对象类型</param>
/// <param name="dataTable">数据表</param>
/// <param name="members">需要转换的成员</param>
/// <param name="ignoreMembers">忽略转换的成员</param>
/// <returns>返回对象数组</returns>
public virtual object[] ConvertTable(Type type, DataTable dataTable, string[] members, string[] ignoreMembers)
{
    // 创建目标对象数组
    object[] objs = Array.CreateInstance(type, dataTable.Rows.Count) as object[];
    // 创建要转换的对象成员字典
    Dictionary<string, MemberInfo> memberInfos = new Dictionary<string, MemberInfo>();
    // 遍历数据表中所有列,添加要转换的对象成员到字典中
    foreach (DataColumn dataColumn in dataTable.Columns)
    {
        // 获取列名
        string name = dataColumn.ColumnName;
        // 判断当前列是否需要转换
        if ((members == null || members.Length <= 0 || members.Contains("*") || members.Contains(name)) && (ignoreMembers == null || ignoreMembers.Length <= 0 || (!ignoreMembers.Contains("*") && !ignoreMembers.Contains(name))))
        {
            // 根据当前列名获取成员属性
            PropertyInfo propertyInfo = type.GetProperty(name);
            // 判断是否有对应名称的成员属性
            if (propertyInfo == null)
            {
                // 根据当前列名获取成员字段
                FieldInfo fieldInfo = type.GetField(name);
                // 判断成员字段是否存在并且是否是公开可写的
                if (fieldInfo != null && fieldInfo.IsPublic && !fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
                {
                    // 添加要转换的对象成员
                    memberInfos[name] = fieldInfo;
                }
            }
            else
            {
                // 判断成员属性是否可写
                if (propertyInfo.CanWrite)
                {
                    // 获取成员属性的SET访问器
                    MethodInfo methodInfo = propertyInfo.GetSetMethod();
                    // 判断成员属性的SET访问器是否是公开的
                    if (methodInfo.IsPublic)
                    {
                        // 添加要转换的对象成员
                        memberInfos[name] = propertyInfo;
                    }
                }
            }
        }
    }
    // 遍历转换数据表中的所有行
    for (int i = 0, length = dataTable.Rows.Count; i < length; i++)
    {
        // 获取对应索引的数据行
        DataRow dataRow = dataTable.Rows[i];
        // 根据对象类型创建目标对象
        object obj = Activator.CreateInstance(type);
        // 遍历要转换的对象成员字典,转换成员数据
        foreach (KeyValuePair<string, MemberInfo> item in memberInfos)
        {
            // 获取当前行对应当前列的数据
            object value = dataRow[item.Key];
            // 获取对象成员
            MemberInfo membeInfo = item.Value;
            // 判断对象成员是否是属性
            if (membeInfo is PropertyInfo)
            {
                // 获取成员属性
                PropertyInfo propertyInfo = membeInfo as PropertyInfo;
                // 根据成员属性类型转换数据类型
                value = this.ConvertType(value, propertyInfo.PropertyType);
                // 判断数据转换是否成功
                if (value != null)
                {
                    // 获取成员属性的SET访问器
                    MethodInfo methodInfo = propertyInfo.GetSetMethod();
                    // 判断成员属性的SET访问器是否是静态的
                    if (methodInfo.IsStatic)
                    {
                        // 设置成员属性的静态值
                        propertyInfo.SetValue(null, value, null);
                    }
                    else
                    {
                        // 设置成员属性的实例值
                        propertyInfo.SetValue(obj, value, null);
                    }
                }
            }
            else
            {
                // 获取成员字段
                FieldInfo fieldInfo = membeInfo as FieldInfo;
                // 根据成员字段类型转换数据类型
                value = this.ConvertType(value, fieldInfo.FieldType);
                // 判断数据转换是否成功
                if (value != null)
                {
                    // 判断成员字段是否是静态的
                    if (fieldInfo.IsStatic)
                    {
                        // 设置成员字段的静态值
                        fieldInfo.SetValue(null, value);
                    }
                    else
                    {
                        // 设置成员字段的实例值
                        fieldInfo.SetValue(obj, value);
                    }
                }
            }
        }
        // 设置目标对象到对象数组中
        objs[i] = obj;
    }
    // 返回目标对象数组
    return objs;
}

发表评论