取消

类型转换

部分类型没有不能进行隐式类型转换,在反射通过属性的SetValue方法赋值时就会报错,比如int32和float?,把int32的值赋值给float?属性就会报错。这里进行一次类型转换,这样就可以了。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/// <summary>
/// 泛型类型转换
/// </summary>
/// <typeparam name="type">要转换的基础类型</typeparam>
/// <param name="val">要转换的值</param>
/// <returns></returns>
public static object ConvertType(Type type, object val)
{
    //泛型Nullable判断,取其中的类型
    if (type.IsGenericType)
    {
        type = type.GetGenericArguments()[0];
    }
    //string直接返回转换
    if (type.Name.ToLower() == "string")
    {
        return val+"";
    }
    //反射获取TryParse方法
    var tryParse = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder,
        new Type[] { typeof(string), type.MakeByRefType() },
        new ParameterModifier[] { new ParameterModifier(2) });
    var parameters = new object[] { val + "", Activator.CreateInstance(type) };
    var success = (bool?)tryParse?.Invoke(null, parameters);
    //成功返回转换后的值,否则返回原值
    return success == true ? parameters[1] : val;
}

使用表达式树生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    /// <summary>
    /// DataTable生成实体
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataTable"></param>
    /// <returns></returns>
    public static IEnumerable<T> ToList<T>(this DataTable dataTable) where T : class, new()
    {
        if (dataTable == null)
            throw new ArgumentNullException(nameof(dataTable));

        List<T> collection = new List<T>(dataTable.Rows.Count);
        if (dataTable.Rows.Count == 0)
        {
            return collection;
        }
        Func<DataRow, T> func = ToExpression<T>(dataTable.Rows[0]);

        foreach (DataRow dr in dataTable.Rows)
        {
            collection.Add(func(dr));
        }
        return collection;
    }

    /// <summary>
    /// 生成表达式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataRow"></param>
    /// <returns></returns>
    public static Func<DataRow, T> ToExpression<T>(DataRow dataRow) where T : class, new()
    {
        if (dataRow == null) throw new ArgumentNullException("dataRow", "当前对象为null 无法转换成实体");
        ParameterExpression paramter = Expression.Parameter(typeof(DataRow), "dr");
        List<MemberBinding> binds = new List<MemberBinding>();
        for (int i = 0; i < dataRow.ItemArray.Length; i++)
        {
            String colName = dataRow.Table.Columns[i].ColumnName;
            PropertyInfo pInfo = typeof(T).GetProperty(colName);
            if (pInfo == null) continue;
            MethodInfo mInfo = typeof(DataRowExtensions)
                .GetMethod("Field",
                    new Type[] { typeof(DataRow), typeof(String) }
                    )
                .MakeGenericMethod(pInfo.PropertyType);
            MethodCallExpression call = Expression.Call(mInfo, paramter, Expression.Constant(colName, typeof(String)));
            var block = Expression.Block(call);
            // if (
            //     pInfo.PropertyType.Name != dataRow.Table.Columns[i].DataType.Name
            //     && pInfo.PropertyType.GetGenericArguments()[0].Name != dataRow.Table.Columns[i].DataType.Name
            // )
            // {
            //     var toString = dataRow.Table.Columns[i].DataType.GetMethod("ToString", new Type[] { });
            //     var toStringEx = Expression.Call(call, toString);

            //     var tp = pInfo.PropertyType.IsGenericType ? pInfo.PropertyType.GetGenericArguments()[0] : pInfo.PropertyType;
            //     MethodInfo tryParse = tp
            //         .GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder,
            //             new Type[] { typeof(string), tp.MakeByRefType() },
            //             new ParameterModifier[] { new ParameterModifier(2) });
            //     ParameterExpression result = Expression.Parameter(typeof(DataRow), "result");
            //     var tryParseEx = Expression.Call(tryParse, toStringEx, result);

            //     block = Expression.Block(tryParseEx);
            // }
            MemberAssignment bind = Expression.Bind(pInfo, block);
            binds.Add(bind);
        }
        MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray());
        return Expression.Lambda<Func<DataRow, T>>(init, paramter).Compile();
    }

本文会经常更新,请阅读原文: https://dashenxian.github.io/post/%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2 ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 小神仙 (包含链接: https://dashenxian.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (125880321@qq.com)

登录 GitHub 账号进行评论