forked from szgit/Helper.Core.Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CopyHelper.cs
207 lines (191 loc) · 12.2 KB
/
CopyHelper.cs
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
* 作用:实体属性值之前相互拷贝。
* 联系:QQ 100101392
* 来源:https://github.com/snipen/Helper.Core.Library
* */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
namespace Helper.Core.Library
{
public class CopyHelper
{
#region 对外公开方法
/// <summary>
/// 复制数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="originalData">原实体数据</param>
/// <param name="propertyMatchList">属性匹配,例:new { ID = "UserID" }</param>
/// <param name="propertyIgnore">忽略属性列表,例:new { ID = "" }</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static T Copy<T>(object originalData, object propertyMatchList = null, object propertyIgnore = null, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression) where T : class, new()
{
Dictionary<PropertyInfo, string> propertyMatchDict = InitPropertyMatchMapper(originalData.GetType(), typeof(T), propertyMatchList, propertyIgnore);
dynamic propertyGetDict = ReflectionExtendHelper.PropertyGetCallDict(originalData.GetType(), reflectionType);
dynamic propertySetDict = ReflectionExtendHelper.PropertySetCallDict<T>(reflectionType);
return CopyData(typeof(T), propertySetDict, propertyGetDict, propertyMatchDict, originalData, propertyMatchList, propertyIgnore, reflectionType) as T;
}
/// <summary>
/// 复制数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="K">拥有索引器的实体类型</typeparam>
/// <typeparam name="P">索引器参数类型,例:int</typeparam>
/// <typeparam name="R">索引器返回类型,例:string</typeparam>
/// <param name="originalData">原实体数据</param>
/// <param name="propertyMatchList">属性匹配,例:new { ID = "UserID" }</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static T Copy<T, K, P, R>(K originalData, object propertyMatchList = null, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression)
where T : class, new()
where K : class
{
T t = ReflectionGenericHelper.New<T>();
Func<K, P, object> indexCall = ReflectionGenericHelper.PropertyIndexGetCall<K, P, R>(reflectionType);
Dictionary<PropertyInfo, string> propertyMatchDict = InitPropertyMatchMapper(originalData.GetType(), typeof(T), propertyMatchList, null);
foreach (var keyValueItem in propertyMatchDict)
{
P indexName = (P)Convert.ChangeType(keyValueItem.Value, typeof(P), CultureInfo.InvariantCulture);
ReflectionHelper.SetPropertyValue(t, indexCall(originalData, indexName).ToString(), keyValueItem.Key);
}
return t;
}
/// <summary>
/// 复制数据
/// </summary>
/// <param name="originalData">原实体数据</param>
/// <param name="targetData">目标实体数据</param>
/// <param name="propertyMatchList">属性匹配,例:new { ID = "UserID" }</param>
/// <param name="propertyIgnore">忽略属性列表,例:new { ID = "" }</param>
/// <param name="reflectionType">反射类型</param>
/// <returns></returns>
public static dynamic Copy(object originalData, object targetData, object propertyMatchList = null, object propertyIgnore = null, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression)
{
Dictionary<PropertyInfo, string> propertyMatchDict = InitPropertyMatchMapper(originalData.GetType(), targetData.GetType(), propertyMatchList, propertyIgnore);
dynamic propertyGetDict = ReflectionExtendHelper.PropertyGetCallDict(originalData.GetType(), reflectionType);
dynamic propertySetDict = ReflectionExtendHelper.PropertySetCallDict(targetData.GetType(), reflectionType);
object copyData = CopyData(targetData, propertySetDict, propertyGetDict, propertyMatchDict, originalData, propertyMatchList, propertyIgnore, reflectionType);
return Convert.ChangeType(copyData, targetData.GetType());
}
#endregion
#region 逻辑处理私有方法
private static Dictionary<PropertyInfo, string> InitPropertyMatchMapper(Type sourceType, Type type, object propertyMatchList = null, object propertyIgnore = null)
{
Dictionary<PropertyInfo, string> resultList = new Dictionary<PropertyInfo, string>();
string matchPropertyName = null;
ReflectionHelper.Foreach((PropertyInfo propertyInfo) =>
{
if (propertyIgnore == null || !ReflectionHelper.IsContainProperty(propertyIgnore.GetType(), propertyInfo.Name))
{
var propertyValue = ReflectionHelper.GetPropertyValue(propertyMatchList, propertyInfo.Name);
if (propertyValue != null)
{
if (ReflectionHelper.IsCustomType(propertyValue.GetType()))
{
var namePropertyValue = ReflectionHelper.GetPropertyValue(propertyValue, "___Name");
if (namePropertyValue != null)
{
matchPropertyName = namePropertyValue.ToString();
}
else
{
matchPropertyName = propertyInfo.Name;
}
}
else
{
matchPropertyName = propertyValue.ToString();
}
}
else
{
matchPropertyName = propertyInfo.Name;
}
if (matchPropertyName != null) resultList.Add(propertyInfo, matchPropertyName);
}
}, type);
return resultList;
}
private static object CopyData(Type type, dynamic propertySetDict, dynamic propertyGetDict, Dictionary<PropertyInfo, string> propertyMatchDict, object originalData, object propertyMatch = null, object propertyIgnore = null, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression)
{
return CopyData(ReflectionHelper.New(type), propertySetDict, propertyGetDict, propertyMatchDict, originalData, propertyMatch, propertyIgnore, reflectionType);
}
private static object CopyData(object targetData, dynamic propertySetDict, dynamic propertyGetDict, Dictionary<PropertyInfo, string> propertyMatchDict, dynamic originalData, object propertyMatch = null, object propertyIgnore = null, ReflectionTypeEnum reflectionType = ReflectionTypeEnum.Expression)
{
if (originalData == null) return targetData;
PropertyInfo propertyInfo = null;
dynamic propertyValue = null;
foreach (var keyValueItem in propertyMatchDict)
{
propertyInfo = keyValueItem.Key;
if (propertyGetDict != null && propertyGetDict.ContainsKey(keyValueItem.Value))
{
propertyValue = propertyGetDict[keyValueItem.Value](originalData);
}
else
{
propertyValue = ReflectionHelper.GetPropertyValue(originalData, keyValueItem.Value);
}
if (propertyValue != null)
{
if (ReflectionHelper.IsListType(propertyInfo.PropertyType))
{
Type originalTType = ReflectionHelper.GetListGenericType(originalData.GetType().GetProperty(keyValueItem.Value));
var originalPropertyMatchValue = ReflectionHelper.GetPropertyValue(propertyMatch, propertyInfo.Name);
var originalPropertyIgnoreValue = ReflectionHelper.GetPropertyValue(propertyIgnore, propertyInfo.Name);
var originalPropertyValue = ReflectionHelper.GetPropertyValue(targetData, propertyInfo) as IList;
Type listTType = ReflectionHelper.GetListGenericType(propertyInfo);
var objectDataList = ReflectionHelper.NewList(listTType) as IList;
dynamic listPropertySetDict = null;
if (reflectionType != ReflectionTypeEnum.Original) listPropertySetDict = ReflectionExtendHelper.PropertySetCallDict(listTType, reflectionType);
dynamic listPropertyGetDict = null;
if (reflectionType != ReflectionTypeEnum.Original) listPropertyGetDict = ReflectionExtendHelper.PropertyGetCallDict(originalTType, reflectionType);
for (int index = 0; index < propertyValue.Count; index++)
{
if (originalPropertyValue != null && index < originalPropertyValue.Count)
{
objectDataList.Add(CopyData(originalPropertyValue[index], listPropertySetDict, listPropertyGetDict, InitPropertyMatchMapper(originalTType, listTType, originalPropertyMatchValue, originalPropertyIgnoreValue), propertyValue[index], originalPropertyMatchValue, originalPropertyIgnoreValue, reflectionType));
}
else
{
objectDataList.Add(CopyData(listTType, listPropertySetDict, listPropertyGetDict, InitPropertyMatchMapper(originalTType, listTType, originalPropertyMatchValue, originalPropertyIgnoreValue), propertyValue[index], originalPropertyMatchValue, originalPropertyIgnoreValue, reflectionType));
}
}
targetData.GetType().GetProperty(propertyInfo.Name).SetValue(targetData, objectDataList, null);
}
else if (ReflectionHelper.IsCustomType(propertyInfo.PropertyType))
{
var originalPropertyMatchValue = ReflectionHelper.GetPropertyValue(propertyMatch, propertyInfo.Name);
var originalPropertyIgnoreValue = ReflectionHelper.GetPropertyValue(propertyIgnore, propertyInfo.Name);
var originalPropertyValue = ReflectionHelper.GetPropertyValue(targetData, propertyInfo);
if (originalPropertyValue == null)
{
targetData.GetType().GetProperty(propertyInfo.Name).SetValue(targetData, CopyData(propertyInfo.PropertyType, null, null, InitPropertyMatchMapper(propertyValue.GetType(), propertyInfo.PropertyType, originalPropertyMatchValue, originalPropertyIgnoreValue), propertyValue, originalPropertyMatchValue, originalPropertyIgnoreValue, reflectionType), null);
}
else
{
targetData.GetType().GetProperty(propertyInfo.Name).SetValue(targetData, CopyData(originalPropertyValue, null, null, InitPropertyMatchMapper(propertyValue.GetType(), propertyInfo.PropertyType, originalPropertyMatchValue, originalPropertyIgnoreValue), propertyValue, originalPropertyMatchValue, originalPropertyIgnoreValue, reflectionType), null);
}
}
else
{
if (propertySetDict != null && propertySetDict.ContainsKey(propertyInfo.Name))
{
ReflectionGenericHelper.SetPropertyValue(propertySetDict[propertyInfo.Name], targetData, propertyValue.ToString(), propertyInfo);
}
else
{
ReflectionHelper.SetPropertyValue(targetData, propertyValue.ToString(), propertyInfo);
}
}
}
}
return targetData;
}
#endregion
}
}