Skip to content

Commit b56fc8a

Browse files
committed
ApiParameterDescriptor修改
1 parent 2697a18 commit b56fc8a

File tree

6 files changed

+229
-270
lines changed

6 files changed

+229
-270
lines changed

WebApiClient/ApiParameterDescriptor.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,6 @@ public class ApiParameterDescriptor : ICloneable
3535
/// </summary>
3636
public object Value { get; internal set; }
3737

38-
/// <summary>
39-
/// 获取参数类型是否为HttpContent类型
40-
/// </summary>
41-
public bool IsHttpContent { get; internal set; }
42-
43-
/// <summary>
44-
/// 获取参数类型是否为IApiParameterable类型
45-
/// </summary>
46-
public bool IsApiParameterable { get; internal set; }
47-
4838
/// <summary>
4939
/// 获取关联的参数特性
5040
/// </summary>
@@ -69,8 +59,6 @@ public object Clone()
6959
{
7060
Attributes = this.Attributes,
7161
Index = this.Index,
72-
IsApiParameterable = this.IsApiParameterable,
73-
IsHttpContent = this.IsHttpContent,
7462
Name = this.Name,
7563
ParameterType = this.ParameterType,
7664
Value = this.Value

WebApiClient/Internal/ApiDescriptorCache.cs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,17 @@ private static ApiParameterDescriptor GetParameterDescriptor(ParameterInfo param
7878
var parameterType = parameter.ParameterType;
7979
var parameterAlias = parameter.GetCustomAttribute(typeof(AliasAsAttribute)) as AliasAsAttribute;
8080
var parameterName = parameterAlias == null ? parameter.Name : parameterAlias.Name;
81-
82-
var descriptor = new ApiParameterDescriptor
83-
{
84-
Attributes = null,
85-
Value = null,
86-
Name = parameterName,
87-
Index = parameter.Position,
88-
ParameterType = parameterType,
89-
IsApiParameterable = parameterType.IsInheritFrom<IApiParameterable>() || parameterType.IsInheritFrom<IEnumerable<IApiParameterable>>(),
90-
IsHttpContent = parameterType.IsInheritFrom<HttpContent>(),
91-
};
81+
var isHttpContent = parameterType.IsInheritFrom<HttpContent>();
82+
var isApiParameterable = parameterType.IsInheritFrom<IApiParameterable>() || parameterType.IsInheritFrom<IEnumerable<IApiParameterable>>();
9283

9384
var defined = parameter.GetAttributes<IApiParameterAttribute>(true);
9485
var attributes = new ParameterAttributeCollection(defined);
9586

96-
if (descriptor.IsApiParameterable == true)
87+
if (isApiParameterable == true)
9788
{
9889
attributes.Add(new ParameterableAttribute());
9990
}
100-
else if (descriptor.IsHttpContent == true)
91+
else if (isHttpContent == true)
10192
{
10293
attributes.AddIfNotExists(new HttpContentAttribute());
10394
}
@@ -106,8 +97,14 @@ private static ApiParameterDescriptor GetParameterDescriptor(ParameterInfo param
10697
attributes.Add(new PathQueryAttribute());
10798
}
10899

109-
descriptor.Attributes = attributes.ToArray();
110-
return descriptor;
100+
return new ApiParameterDescriptor
101+
{
102+
Attributes = attributes.ToArray(),
103+
Index = parameter.Position,
104+
Name = parameterName,
105+
ParameterType = parameterType,
106+
Value = null,
107+
};
111108
}
112109

113110
/// <summary>

WebApiClient/Internal/DefaultJsonFormatter.cs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,7 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
9494
var property = base.CreateProperty(member, memberSerialization);
9595
var descriptor = PropertyDescriptor.GetDescriptor(member);
9696

97-
if (string.IsNullOrEmpty(descriptor.Alias) == false)
98-
{
99-
property.PropertyName = descriptor.Alias;
100-
}
101-
97+
property.PropertyName = descriptor.AliasName;
10298
if (this.useCamelCase == true)
10399
{
104100
property.PropertyName = FormatOptions.CamelCase(property.PropertyName);
@@ -124,9 +120,9 @@ private class PropertyDescriptor
124120
private static readonly ConcurrentDictionary<MemberInfo, PropertyDescriptor> descriptorCache;
125121

126122
/// <summary>
127-
/// 获取别名
123+
/// 获取属性别名或名称
128124
/// </summary>
129-
public string Alias { get; private set; }
125+
public string AliasName { get; private set; }
130126

131127
/// <summary>
132128
/// 获取时间转换器
@@ -144,18 +140,15 @@ private class PropertyDescriptor
144140
/// <param name="member"></param>
145141
private PropertyDescriptor(MemberInfo member)
146142
{
143+
var aliasAs = member.GetAttribute<AliasAsAttribute>(true);
144+
this.AliasName = aliasAs == null ? member.Name : aliasAs.Name;
145+
147146
var datatimeFormat = member.GetAttribute<DateTimeFormatAttribute>(true);
148147
if (datatimeFormat != null)
149148
{
150149
this.DateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = datatimeFormat.Format };
151150
}
152151

153-
var aliasAs = member.GetAttribute<AliasAsAttribute>(true);
154-
if (aliasAs != null)
155-
{
156-
this.Alias = aliasAs.Name;
157-
}
158-
159152
this.IsIgnoreSerialized = member.IsDefined(typeof(IgnoreSerializedAttribute));
160153
}
161154

WebApiClient/Internal/DefaultKeyValueFormatter.cs

Lines changed: 211 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System;
22
using System.Collections;
3+
using System.Collections.Concurrent;
34
using System.Collections.Generic;
45
using System.Globalization;
56
using System.Linq;
7+
using System.Reflection;
68
using System.Text;
79
using System.Threading.Tasks;
810

@@ -100,11 +102,11 @@ private IEnumerable<KeyValuePair<string, string>> FormatAsComplex(object instanc
100102
}
101103

102104
return
103-
from p in KeyValueProperty.GetProperties(instance.GetType())
105+
from p in PropertyDescriptor.GetProperties(instance.GetType())
104106
where p.IsSupportGet && p.IgnoreSerialized == false
105107
let value = p.GetValue(instance)
106108
let opt = options.CloneChange(p.DateTimeFormat)
107-
select this.FormatAsSimple(p.Name, value, opt);
109+
select this.FormatAsSimple(p.AliasName, value, opt);
108110
}
109111

110112
/// <summary>
@@ -157,5 +159,212 @@ private KeyValuePair<string, string> FormatAsSimple(string name, object value, F
157159
var dateTime = ((DateTime)value).ToString(options.DateTimeFormat, DateTimeFormatInfo.InvariantInfo);
158160
return new KeyValuePair<string, string>(name, dateTime);
159161
}
162+
163+
/// <summary>
164+
/// 表示类型描述
165+
/// </summary>
166+
private class TypeDescriptor
167+
{
168+
/// <summary>
169+
/// 描述缓存
170+
/// </summary>
171+
private static readonly ConcurrentDictionary<Type, TypeDescriptor> descriptorCache;
172+
173+
/// <summary>
174+
/// 获取类型是否为简单类型
175+
/// </summary>
176+
public bool IsSimpleType { get; private set; }
177+
178+
/// <summary>
179+
/// 获取类型是否为可列举类型
180+
/// </summary>
181+
public bool IsEnumerable { get; private set; }
182+
183+
/// <summary>
184+
/// 获取类型是否为IDictionaryOf(string,object)
185+
/// </summary>
186+
public bool IsDictionaryOfObject { get; private set; }
187+
188+
/// <summary>
189+
/// 获取类型是否为IDictionaryOf(string,string)
190+
/// </summary>
191+
public bool IsDictionaryOfString { get; private set; }
192+
193+
/// <summary>
194+
/// 类型描述
195+
/// </summary>
196+
/// <param name="type">类型</param>
197+
private TypeDescriptor(Type type)
198+
{
199+
this.IsSimpleType = type.IsSimple();
200+
this.IsEnumerable = type.IsInheritFrom<IEnumerable>();
201+
this.IsDictionaryOfObject = type.IsInheritFrom<IDictionary<string, object>>();
202+
this.IsDictionaryOfString = type.IsInheritFrom<IDictionary<string, string>>();
203+
}
204+
205+
/// <summary>
206+
/// 静态构造器
207+
/// </summary>
208+
static TypeDescriptor()
209+
{
210+
descriptorCache = new ConcurrentDictionary<Type, TypeDescriptor>();
211+
}
212+
213+
/// <summary>
214+
/// 获取类型的描述
215+
/// </summary>
216+
/// <param name="type">类型</param>
217+
/// <returns></returns>
218+
public static TypeDescriptor GetDescriptor(Type type)
219+
{
220+
if (type == null)
221+
{
222+
return null;
223+
}
224+
return descriptorCache.GetOrAdd(type, (t) => new TypeDescriptor(t));
225+
}
226+
}
227+
228+
/// <summary>
229+
/// 表示属性描述
230+
/// </summary>
231+
private class PropertyDescriptor
232+
{
233+
/// <summary>
234+
/// 获取器
235+
/// </summary>
236+
private readonly Getter getter;
237+
238+
/// <summary>
239+
/// 获取属性别名或名称
240+
/// </summary>
241+
public string AliasName { get; private set; }
242+
243+
/// <summary>
244+
/// 获取声明的DateTimeFormatAttribute的Format
245+
/// </summary>
246+
public string DateTimeFormat { get; private set; }
247+
248+
/// <summary>
249+
/// 获取是否声明IgnoreSerializedAttribute
250+
/// </summary>
251+
public bool IgnoreSerialized { get; private set; }
252+
253+
/// <summary>
254+
/// 获取是否支持Get操作
255+
/// </summary>
256+
public bool IsSupportGet { get; private set; }
257+
258+
/// <summary>
259+
/// 属性
260+
/// </summary>
261+
/// <param name="property">属性信息</param>
262+
private PropertyDescriptor(PropertyInfo property)
263+
{
264+
var aliasAs = property.GetAttribute<AliasAsAttribute>(true);
265+
this.AliasName = aliasAs == null ? property.Name : aliasAs.Name;
266+
267+
if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?))
268+
{
269+
var formatAttribute = property.GetAttribute<DateTimeFormatAttribute>(true);
270+
this.DateTimeFormat = formatAttribute == null ? null : formatAttribute.Format;
271+
}
272+
273+
if (property.CanRead == true)
274+
{
275+
this.getter = Getter.Create(property);
276+
}
277+
278+
this.IgnoreSerialized = property.IsDefined(typeof(IgnoreSerializedAttribute));
279+
this.IsSupportGet = this.getter != null;
280+
}
281+
282+
/// <summary>
283+
/// 获取属性的值
284+
/// </summary>
285+
/// <param name="instance">实例</param>
286+
/// <exception cref="NotSupportedException"></exception>
287+
/// <returns></returns>
288+
public object GetValue(object instance)
289+
{
290+
if (this.IsSupportGet == false)
291+
{
292+
throw new NotSupportedException();
293+
}
294+
return this.getter.Invoke(instance);
295+
}
296+
297+
/// <summary>
298+
/// 类型的属性描述缓存
299+
/// </summary>
300+
private static readonly ConcurrentDictionary<Type, PropertyDescriptor[]> propertyCached = new ConcurrentDictionary<Type, PropertyDescriptor[]>();
301+
302+
/// <summary>
303+
/// 从类型的属性获取属性
304+
/// </summary>
305+
/// <param name="classType">类型</param>
306+
/// <returns></returns>
307+
public static PropertyDescriptor[] GetProperties(Type classType)
308+
{
309+
return propertyCached.GetOrAdd(classType, t => t.GetProperties().Select(p => new PropertyDescriptor(p)).ToArray());
310+
}
311+
312+
/// <summary>
313+
/// 表示属性的Get方法抽象类
314+
/// </summary>
315+
private abstract class Getter
316+
{
317+
/// <summary>
318+
/// 创建属性的Get方法
319+
/// </summary>
320+
/// <param name="property">属性</param>
321+
/// <returns></returns>
322+
public static Getter Create(PropertyInfo property)
323+
{
324+
var getterType = typeof(GenericGetter<,>).MakeGenericType(property.DeclaringType, property.PropertyType);
325+
return Activator.CreateInstance(getterType, property) as Getter;
326+
}
327+
328+
/// <summary>
329+
/// 执行Get方法
330+
/// </summary>
331+
/// <param name="instance">实例</param>
332+
/// <returns></returns>
333+
public abstract object Invoke(object instance);
334+
335+
/// <summary>
336+
/// 表示属性的Get方法
337+
/// </summary>
338+
/// <typeparam name="TTarget">属性所在的类</typeparam>
339+
/// <typeparam name="TResult">属性的返回值</typeparam>
340+
private class GenericGetter<TTarget, TResult> : Getter
341+
{
342+
/// <summary>
343+
/// get方法的委托
344+
/// </summary>
345+
private readonly Func<TTarget, TResult> getFunc;
346+
347+
/// <summary>
348+
/// 属性的Get方法
349+
/// </summary>
350+
/// <param name="property">属性</param>
351+
public GenericGetter(PropertyInfo property)
352+
{
353+
var getMethod = property.GetGetMethod();
354+
this.getFunc = (Func<TTarget, TResult>)getMethod.CreateDelegate(typeof(Func<TTarget, TResult>), null);
355+
}
356+
357+
/// <summary>
358+
/// 执行Get方法
359+
/// </summary>
360+
/// <param name="instance">实例</param>
361+
/// <returns></returns>
362+
public override object Invoke(object instance)
363+
{
364+
return this.getFunc.Invoke((TTarget)instance);
365+
}
366+
}
367+
}
368+
}
160369
}
161370
}

0 commit comments

Comments
 (0)