Skip to content

Commit e1a5267

Browse files
committed
优化数据导入器基类,完善对字典类型的数据支持。 🐦
1 parent 3540574 commit e1a5267

1 file changed

Lines changed: 92 additions & 81 deletions

File tree

Zongsoft.Data/src/Common/DataImporterBase.cs

Lines changed: 92 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
using System.Threading.Tasks;
3434
using System.Reflection;
3535

36+
using Zongsoft.Reflection;
37+
using Zongsoft.Collections;
38+
3639
namespace Zongsoft.Data.Common;
3740

3841
public abstract class DataImporterBase : IDataImporter
@@ -50,49 +53,76 @@ public abstract class DataImporterBase : IDataImporter
5053
#region 私有方法
5154
private static MemberCollection GetMembers(DataImportContext context)
5255
{
53-
static MemberInfo GetMemberInfo(Type type, string name)
54-
{
55-
if(typeof(System.Collections.IDictionary).IsAssignableFrom(type))
56-
{
57-
var indexes = type.GetDefaultMembers();
58-
return indexes != null && indexes.Length > 0 ? indexes[0] : type.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance);
59-
}
56+
var members = new MemberCollection();
6057

61-
return (MemberInfo)type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance) ??
62-
(MemberInfo)type.GetField(name, BindingFlags.Public | BindingFlags.Instance);
63-
}
58+
if(typeof(System.Collections.IDictionary).IsAssignableFrom(context.ModelType))
59+
GenerateMembersWithoutInfo(context, members);
60+
else
61+
GenerateMembersWithInfo(context, members);
6462

65-
var members = new MemberCollection();
63+
return members;
6664

67-
if(context.Members == null || context.Members.Length == 0)
65+
static MemberInfo GetMemberInfo(Type type, string name) =>
66+
(MemberInfo)type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance) ??
67+
(MemberInfo)type.GetField(name, BindingFlags.Public | BindingFlags.Instance);
68+
69+
static void GenerateMembersWithInfo(DataImportContext context, MemberCollection members)
6870
{
69-
foreach(var property in context.Entity.Properties)
71+
if(context.Members == null || context.Members.Length == 0)
7072
{
71-
if(property.IsComplex)
72-
continue;
73+
foreach(var property in context.Entity.Properties)
74+
{
75+
if(property.IsComplex)
76+
continue;
7377

74-
var info = GetMemberInfo(context.ModelType, property.Name);
75-
if(info != null)
76-
members.Add(new Member(context, info, (Metadata.IDataEntitySimplexProperty)property));
78+
var info = GetMemberInfo(context.ModelType, property.Name);
79+
if(info != null)
80+
members.Add(new Member(context, (Metadata.IDataEntitySimplexProperty)property, info));
81+
}
82+
}
83+
else
84+
{
85+
for(int i = 0; i < context.Members.Length; i++)
86+
{
87+
if(context.Entity.Properties.TryGetValue(context.Members[i], out var property))
88+
{
89+
if(property.IsComplex)
90+
throw new DataException($"The specified '{property.Name}' property cannot be a navigation property, only scalar field data can be import.");
91+
92+
var info = GetMemberInfo(context.ModelType, property.Name);
93+
if(info != null)
94+
members.Add(new Member(context, (Metadata.IDataEntitySimplexProperty)property, info));
95+
}
96+
}
7797
}
7898
}
79-
else
99+
100+
static void GenerateMembersWithoutInfo(DataImportContext context, MemberCollection members)
80101
{
81-
for(int i = 0; i < context.Members.Length; i++)
102+
if(context.Members == null || context.Members.Length == 0)
82103
{
83-
if(context.Entity.Properties.TryGetValue(context.Members[i], out var property))
104+
foreach(var property in context.Entity.Properties)
84105
{
85106
if(property.IsComplex)
86-
throw new DataException($"The specified '{property.Name}' property cannot be a navigation property, only scalar field data can be import.");
107+
continue;
87108

88-
var info = GetMemberInfo(context.ModelType, property.Name);
89-
if(info != null)
90-
members.Add(new Member(context, info, (Metadata.IDataEntitySimplexProperty)property));
109+
members.Add(new Member(context, (Metadata.IDataEntitySimplexProperty)property, null));
91110
}
92111
}
93-
}
112+
else
113+
{
114+
for(int i = 0; i < context.Members.Length; i++)
115+
{
116+
if(context.Entity.Properties.TryGetValue(context.Members[i], out var property))
117+
{
118+
if(property.IsComplex)
119+
throw new DataException($"The specified '{property.Name}' property cannot be a navigation property, only scalar field data can be import.");
94120

95-
return members;
121+
members.Add(new Member(context, (Metadata.IDataEntitySimplexProperty)property, null));
122+
}
123+
}
124+
}
125+
}
96126
}
97127
#endregion
98128

@@ -102,47 +132,43 @@ public readonly struct Member
102132
#region 私有变量
103133
private readonly DataImportContextBase _context;
104134
private readonly IDataValidator _validator;
105-
106-
private readonly Reflection.FieldInfoExtension.Getter _fieldGetter;
107-
private readonly Reflection.FieldInfoExtension.Setter _fieldSetter;
108-
private readonly Reflection.PropertyInfoExtension.Getter _propertyGetter;
109-
private readonly Reflection.PropertyInfoExtension.Setter _propertySetter;
110135
private readonly Delegate _getter;
111136
private readonly Delegate _setter;
112137
private readonly bool _isIndexer;
113138
#endregion
114139

115140
#region 构造函数
116-
public Member(DataImportContextBase context, MemberInfo info, Metadata.IDataEntityProperty property)
141+
public Member(DataImportContextBase context, Metadata.IDataEntityProperty property, MemberInfo member)
117142
{
118143
_context = context ?? throw new ArgumentNullException(nameof(context));
119144
_validator = DataEnvironment.Validators.GetValidator(context);
120-
this.Info = info ?? throw new ArgumentNullException(nameof(info));
121145
this.Property = property ?? throw new ArgumentNullException(nameof(property));
122146
this.Name = property.Name;
123147

124-
switch(info)
148+
switch(member)
125149
{
126150
case FieldInfo fieldInfo:
127-
_fieldGetter = Reflection.FieldInfoExtension.GetGetter(fieldInfo);
128-
_fieldSetter = Reflection.FieldInfoExtension.GetSetter(fieldInfo);
129-
_getter = Reflection.FieldInfoExtension.GetGetter(fieldInfo);
130-
_setter = Reflection.FieldInfoExtension.GetSetter(fieldInfo);
151+
this.Type = fieldInfo.FieldType;
152+
_getter = fieldInfo.GetGetter();
153+
_setter = fieldInfo.GetSetter();
131154
break;
132155
case PropertyInfo propertyInfo:
133-
_propertyGetter = Reflection.PropertyInfoExtension.GetGetter(propertyInfo);
134-
_propertySetter = Reflection.PropertyInfoExtension.GetSetter(propertyInfo);
135-
156+
this.Type = propertyInfo.PropertyType;
157+
_getter = propertyInfo.GetGetter();
158+
_setter = propertyInfo.GetSetter();
159+
_isIndexer = propertyInfo.GetIndexParameters().Length > 0;
136160
break;
137161
default:
138-
throw new ArgumentException($"The specified '{info.Name}' info is invalid member.");
162+
if(member != null)
163+
throw new ArgumentException($"The specified '{member.Name}' info is invalid member.");
164+
break;
139165
}
140166
}
141167
#endregion
142168

143169
#region 公共字段
144170
public readonly string Name;
145-
public readonly MemberInfo Info;
171+
public readonly Type Type;
146172
public readonly Metadata.IDataEntityProperty Property;
147173
#endregion
148174

@@ -170,13 +196,13 @@ public object GetValue(ref object target)
170196
if(CanSequence(property.Sequence))
171197
{
172198
//获取目标的当前属性值,如果获取失败或其值为空或数字零,则递增该字段序号
173-
if(!this.TryGetValue(ref target, out value) || value == null || Convert.IsDBNull(value) || Zongsoft.Common.Convert.IsZero(value))
199+
if(!this.TryGetMemberValue(ref target, out value) || value == null || Convert.IsDBNull(value) || Zongsoft.Common.Convert.IsZero(value))
174200
{
175201
//递增当前属性对应的序号
176202
var id = _context.DataAccess.Sequencer.Increase(property);
177203

178204
//尝试将递增的序号值写入到目标对象的属性
179-
this.TrySetValue(ref target, type => Zongsoft.Common.Convert.ConvertValue(id, type));
205+
this.SetMemberValue(ref target, Zongsoft.Common.Convert.ConvertValue(id, this.Type));
180206

181207
//返回最新的序号值
182208
return Convert.ChangeType(id, property.Type.DbType.AsType());
@@ -187,13 +213,13 @@ public object GetValue(ref object target)
187213
if(_validator != null && _validator.OnImport(_context, this.Property, out value))
188214
{
189215
//尝试验证器返回的值写入到目标对象的属性
190-
this.TrySetValue(ref target, value);
216+
this.SetMemberValue(ref target, value);
191217

192218
//返回验证后的值
193219
return ConvertValue(value, property.Type, property.Length, property.Nullable);
194220
}
195221

196-
if(this.TryGetValue(ref target, out value))
222+
if(this.TryGetMemberValue(ref target, out value))
197223
return ConvertValue(value == null || value is string text && string.IsNullOrEmpty(text) ? property.DefaultValue : value, property.Type, property.Length, property.Nullable);
198224
else
199225
return ConvertValue(property.DefaultValue, property.Type, property.Length, property.Nullable);
@@ -226,47 +252,32 @@ static bool IsString(DbType dbType) =>
226252
#endregion
227253

228254
#region 私有方法
229-
private object GetFieldValue(ref object target) => ((Reflection.FieldInfoExtension.Getter)_getter).Invoke(ref target);
230-
private void SetFieldValue(ref object target, object value) => ((Reflection.FieldInfoExtension.Setter)_setter).Invoke(ref target, value);
231-
private object GetPropertyValue(ref object target) => ((Reflection.PropertyInfoExtension.Getter)_getter).Invoke(ref target);
232-
233-
private bool TryGetValue(ref object target, out object value)
255+
private bool TryGetMemberValue(ref object target, out object value)
234256
{
235-
if(this.Info is PropertyInfo property)
236-
{
237-
var parameters = property.GetIndexParameters();
238-
if(parameters != null && parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
239-
return Reflection.Reflector.TryGetValue(property, ref target, [this.Name], out value);
257+
if(target is System.Collections.IDictionary dictionary)
258+
return dictionary.TryGetValue(this.Name, out value);
240259

241-
var getter = Reflection.PropertyInfoExtension.GetGetter(property);
242-
getter.Invoke(ref target, this.Name);
243-
}
260+
if(_getter is FieldInfoExtension.Getter getter)
261+
value = getter.Invoke(ref target);
244262

245-
return Reflection.Reflector.TryGetValue(this.Info, ref target, out value);
246-
}
263+
value = _isIndexer ?
264+
((PropertyInfoExtension.Getter)_getter).Invoke(ref target, this.Name) :
265+
((PropertyInfoExtension.Getter)_getter).Invoke(ref target);
247266

248-
private bool TrySetValue(ref object target, object value)
249-
{
250-
if(this.Info is PropertyInfo property)
251-
{
252-
var parameters = property.GetIndexParameters();
253-
if(parameters != null && parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
254-
return Reflection.Reflector.TrySetValue(property, ref target, value, this.Name);
255-
}
256-
257-
return Reflection.Reflector.TrySetValue(this.Info, ref target, value);
267+
return true;
258268
}
259269

260-
private bool TrySetValue(ref object target, Func<Type, object> valueFactory)
270+
private void SetMemberValue(ref object target, object value)
261271
{
262-
if(this.Info is PropertyInfo property)
263-
{
264-
var parameters = property.GetIndexParameters();
265-
if(parameters != null && parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
266-
return Reflection.Reflector.TrySetValue(property, ref target, valueFactory, this.Name);
267-
}
272+
if(target is System.Collections.IDictionary dictionary)
273+
dictionary[this.Name] = value;
268274

269-
return Reflection.Reflector.TrySetValue(this.Info, ref target, valueFactory);
275+
if(_setter is FieldInfoExtension.Setter setter)
276+
setter.Invoke(ref target, value);
277+
else if(_isIndexer)
278+
((PropertyInfoExtension.Setter)_setter).Invoke(ref target, value, this.Name);
279+
else
280+
((PropertyInfoExtension.Setter)_setter).Invoke(ref target, value);
270281
}
271282

272283
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)