部分类型没有不能进行隐式类型转换,在反射通过属性的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) 。