Skip to content

Commit 16a94a7

Browse files
committed
Move class and property info lookup to separate class.
1 parent bb5da1e commit 16a94a7

File tree

2 files changed

+104
-50
lines changed

2 files changed

+104
-50
lines changed

PhpSerializerNET/PhpDeserializer.cs

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@ internal class PhpDeserializer {
1616
private readonly PhpDeserializationOptions _options;
1717
private readonly PhpSerializeToken _token;
1818

19-
private static readonly Dictionary<string, Type> TypeLookupCache = new() {
20-
{ "DateTime", typeof(PhpDateTime) }
21-
};
22-
private static readonly object TypeLookupCacheSyncObject = new();
23-
24-
private static readonly Dictionary<Type, Dictionary<object, PropertyInfo>> PropertyInfoCache = new();
25-
private static readonly object PropertyInfoCacheSyncObject = new();
26-
2719
private static Dictionary<Type, Dictionary<string, FieldInfo>> FieldInfoCache { get; set; } = new();
2820
private static readonly object FieldInfoCacheCacheSyncObject = new();
2921

@@ -55,20 +47,15 @@ public T Deserialize<T>() {
5547
/// Can be useful for scenarios in which new types are loaded at runtime in between deserialization tasks.
5648
/// </summary>
5749
public static void ClearTypeCache() {
58-
lock (TypeLookupCache) {
59-
TypeLookupCache.Clear();
60-
TypeLookupCache.Add("DateTime", typeof(PhpDateTime));
61-
}
50+
TypeLookup.ClearTypeCache();
6251
}
6352

6453
/// <summary>
6554
/// Reset the property info cache.
6655
/// Can be useful for scenarios in which new types are loaded at runtime in between deserialization tasks.
6756
/// </summary>
6857
public static void ClearPropertyInfoCache() {
69-
lock (PropertyInfoCacheSyncObject) {
70-
PropertyInfoCache.Clear();
71-
}
58+
TypeLookup.ClearPropertyInfoCache();
7259

7360
lock (EnumInfoCacheSyncObject) {
7461
EnumInfoCache.Clear();
@@ -103,30 +90,7 @@ private object MakeClass(PhpSerializeToken token) {
10390
object constructedObject;
10491
Type targetType = null;
10592
if (typeName != "stdClass" && this._options.EnableTypeLookup) {
106-
lock (TypeLookupCacheSyncObject) {
107-
if (TypeLookupCache.ContainsKey(typeName)) {
108-
targetType = TypeLookupCache[typeName];
109-
} else {
110-
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic)) {
111-
112-
targetType = assembly
113-
.GetExportedTypes()
114-
.Select(type => new { type, attribute = type.GetCustomAttribute<PhpClass>() })
115-
// PhpClass attribute should win over classes who happen to have the name
116-
.OrderBy(c => c.attribute != null ? 0 : 1)
117-
.Where(y => y.type.Name == typeName || y.attribute?.Name == typeName)
118-
.Select(c => c.type)
119-
.FirstOrDefault();
120-
121-
if (targetType != null) {
122-
break;
123-
}
124-
}
125-
if (this._options.TypeCache.HasFlag(TypeCacheFlag.ClassNames)) {
126-
TypeLookupCache.Add(typeName, targetType);
127-
}
128-
}
129-
}
93+
targetType = TypeLookup.FindTypeInAssymbly(typeName, this._options.TypeCache.HasFlag(TypeCacheFlag.ClassNames));
13094
}
13195
if (targetType != null && typeName != "stdClass") {
13296
constructedObject = this.DeserializeToken(targetType, token);
@@ -392,17 +356,7 @@ private object MakeStruct(Type targetType, PhpSerializeToken token) {
392356

393357
private object MakeObject(Type targetType, PhpSerializeToken token) {
394358
var result = Activator.CreateInstance(targetType);
395-
Dictionary<object, PropertyInfo> properties;
396-
lock (PropertyInfoCacheSyncObject) {
397-
if (PropertyInfoCache.ContainsKey(targetType)) {
398-
properties = PropertyInfoCache[targetType];
399-
} else {
400-
properties = targetType.GetProperties().GetAllProperties(this._options);
401-
if (this._options.TypeCache.HasFlag(TypeCacheFlag.PropertyInfo)) {
402-
PropertyInfoCache.Add(targetType, properties);
403-
}
404-
}
405-
}
359+
Dictionary<object, PropertyInfo> properties = TypeLookup.GetPropertyInfos(targetType, this._options);
406360

407361
for (int i = 0; i < token.Children.Length; i += 2) {
408362
object propertyName;

PhpSerializerNET/TypeLookup.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
This Source Code Form is subject to the terms of the Mozilla Public
3+
License, v. 2.0. If a copy of the MPL was not distributed with this
4+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
5+
**/
6+
7+
using System;
8+
using System.Collections;
9+
using System.Collections.Generic;
10+
using System.Globalization;
11+
using System.Linq;
12+
using System.Reflection;
13+
14+
15+
namespace PhpSerializerNET {
16+
17+
public static class TypeLookup {
18+
private static readonly Dictionary<string, Type> TypeLookupCache = new() {
19+
{ "DateTime", typeof(PhpDateTime) }
20+
};
21+
22+
private static readonly Dictionary<Type, Dictionary<object, PropertyInfo>> PropertyInfoCache = new();
23+
24+
25+
/// <summary>
26+
/// Reset the type lookup cache.
27+
/// Can be useful for scenarios in which new types are loaded at runtime in between deserialization tasks.
28+
/// </summary>
29+
public static void ClearTypeCache() {
30+
lock (TypeLookupCache) {
31+
TypeLookupCache.Clear();
32+
TypeLookupCache.Add("DateTime", typeof(PhpDateTime));
33+
}
34+
}
35+
36+
/// <summary>
37+
/// Reset the property info cache.
38+
/// Can be useful for scenarios in which new types are loaded at runtime in between deserialization tasks.
39+
/// </summary>
40+
public static void ClearPropertyInfoCache() {
41+
lock (PropertyInfoCache) {
42+
PropertyInfoCache.Clear();
43+
}
44+
45+
// lock (EnumInfoCacheSyncObject) {
46+
// EnumInfoCache.Clear();
47+
// }
48+
}
49+
50+
public static Type FindTypeInAssymbly(string typeName, bool cacheEnabled) {
51+
Type result = null;
52+
if (cacheEnabled) {
53+
lock (TypeLookupCache) {
54+
if (TypeLookupCache.ContainsKey(typeName)) {
55+
return TypeLookupCache[typeName];
56+
}
57+
}
58+
}
59+
60+
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic)) {
61+
result = assembly
62+
.GetExportedTypes()
63+
.Select(type => new { type, attribute = type.GetCustomAttribute<PhpClass>() })
64+
// PhpClass attribute should win over classes who happen to have the name
65+
.OrderBy(c => c.attribute != null ? 0 : 1)
66+
.Where(y => y.type.Name == typeName || y.attribute?.Name == typeName)
67+
.Select(c => c.type)
68+
.FirstOrDefault();
69+
70+
if (result != null) {
71+
break;
72+
}
73+
}
74+
if (cacheEnabled) {
75+
lock (TypeLookupCache) {
76+
TypeLookupCache.Add(typeName, result);
77+
}
78+
}
79+
return result;
80+
}
81+
82+
public static Dictionary<object, PropertyInfo> GetPropertyInfos(Type type, PhpDeserializationOptions options) {
83+
bool cacheEnabled = options.TypeCache.HasFlag(TypeCacheFlag.PropertyInfo);
84+
if (cacheEnabled) {
85+
lock (PropertyInfoCache) {
86+
if (PropertyInfoCache.ContainsKey(type)) {
87+
return PropertyInfoCache[type];
88+
}
89+
}
90+
}
91+
Dictionary<object, PropertyInfo> properties = type.GetProperties().GetAllProperties(options);
92+
if (cacheEnabled) {
93+
lock (PropertyInfoCache) {
94+
PropertyInfoCache.Add(type, properties);
95+
}
96+
}
97+
return properties;
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)