Skip to content

Commit 7f2ba90

Browse files
committed
Lazily load dynamic linq types
1 parent 53361d6 commit 7f2ba90

File tree

2 files changed

+25
-20
lines changed

2 files changed

+25
-20
lines changed

src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
using System.Linq.Dynamic.Core.Validation;
33
using System.Reflection;
44
using System.Runtime.CompilerServices;
5+
using System.Threading;
56

67
namespace System.Linq.Dynamic.Core.CustomTypeProviders;
78

89
/// <summary>
910
/// The default implementation for <see cref="DefaultDynamicLinqCustomTypeProvider"/>.
10-
///
11+
///
1112
/// Scans the current AppDomain for all types marked with <see cref="DynamicLinqTypeAttribute"/>, and adds them as custom Dynamic Link types.
1213
///
1314
/// This class is used as default for full .NET Framework and .NET Core App 2.x and higher.
@@ -16,8 +17,8 @@ public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTyp
1617
{
1718
private readonly IAssemblyHelper _assemblyHelper;
1819
private readonly bool _cacheCustomTypes;
20+
private readonly Lazy<HashSet<Type>>? _cachedCustomTypes;
1921

20-
private HashSet<Type>? _cachedCustomTypes;
2122
private Dictionary<Type, List<MethodInfo>>? _cachedExtensionMethods;
2223

2324
/// <summary>
@@ -49,19 +50,17 @@ public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, IList<Type> ad
4950
{
5051
_assemblyHelper = new DefaultAssemblyHelper(Check.NotNull(config));
5152
_cacheCustomTypes = cacheCustomTypes;
53+
_cachedCustomTypes = cacheCustomTypes
54+
? new Lazy<HashSet<Type>>(GetCustomTypesInternal, LazyThreadSafetyMode.ExecutionAndPublication)
55+
: null;
5256
}
5357

5458
/// <inheritdoc cref="IDynamicLinqCustomTypeProvider.GetCustomTypes"/>
5559
public virtual HashSet<Type> GetCustomTypes()
5660
{
5761
if (_cacheCustomTypes)
5862
{
59-
if (_cachedCustomTypes == null)
60-
{
61-
_cachedCustomTypes = GetCustomTypesInternal();
62-
}
63-
64-
return _cachedCustomTypes;
63+
return _cachedCustomTypes!.Value;
6564
}
6665

6766
return GetCustomTypesInternal();

src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Linq.Dynamic.Core.Validation;
33
using System.Linq.Expressions;
4+
using System.Threading;
45
using AnyOfTypes;
56

67
namespace System.Linq.Dynamic.Core.Parser;
@@ -32,7 +33,7 @@ internal class KeywordsHelper : IKeywordsHelper
3233
private static readonly Dictionary<string, Type> PreDefinedTypeMapping = new();
3334

3435
// Custom DefinedTypes are not IgnoreCase
35-
private readonly Dictionary<string, Type> _customTypeMapping = new();
36+
private readonly Lazy<Dictionary<string, Type>> _customTypeMapping;
3637

3738
static KeywordsHelper()
3839
{
@@ -66,22 +67,27 @@ public KeywordsHelper(ParsingConfig config)
6667
{ FUNCTION_CAST, FUNCTION_CAST }
6768
};
6869

70+
_customTypeMapping = new Lazy<Dictionary<string, Type>>(() =>
71+
{
72+
Dictionary<string, Type> customTypeMapping = new();
73+
if (config.CustomTypeProvider != null)
74+
{
75+
foreach (var type in config.CustomTypeProvider.GetCustomTypes())
76+
{
77+
customTypeMapping[type.FullName!] = type;
78+
customTypeMapping[type.Name] = type;
79+
}
80+
}
81+
82+
return customTypeMapping;
83+
}, LazyThreadSafetyMode.PublicationOnly);
84+
6985
if (config.AreContextKeywordsEnabled)
7086
{
7187
_mappings.Add(KEYWORD_IT, KEYWORD_IT);
7288
_mappings.Add(KEYWORD_PARENT, KEYWORD_PARENT);
7389
_mappings.Add(KEYWORD_ROOT, KEYWORD_ROOT);
7490
}
75-
76-
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
77-
if (config.CustomTypeProvider != null)
78-
{
79-
foreach (var type in config.CustomTypeProvider.GetCustomTypes())
80-
{
81-
_customTypeMapping[type.FullName!] = type;
82-
_customTypeMapping[type.Name] = type;
83-
}
84-
}
8591
}
8692

8793
public bool IsItOrRootOrParent(AnyOf<string, Expression, Type> value)
@@ -125,7 +131,7 @@ public bool TryGetValue(string text, out AnyOf<string, Expression, Type> value)
125131
}
126132

127133
// 5. Try to get as custom type
128-
if (_customTypeMapping.TryGetValue(text, out var customType))
134+
if (_customTypeMapping.Value.TryGetValue(text, out var customType))
129135
{
130136
value = customType;
131137
return true;

0 commit comments

Comments
 (0)