Skip to content

Commit efaa34c

Browse files
authored
Update AbstractDynamicLinqCustomTypeProvider to exclude null types (#665)
* Update AbstractDynamicLinqCustomTypeProvider * . * .
1 parent f7b42ed commit efaa34c

File tree

3 files changed

+136
-122
lines changed

3 files changed

+136
-122
lines changed

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Copyright>Copyright © ZZZ Projects</Copyright>
88
<DefaultLanguage>en-us</DefaultLanguage>
99
<GenerateDocumentationFile>true</GenerateDocumentationFile>
10-
<LangVersion>10</LangVersion>
10+
<LangVersion>11</LangVersion>
1111
<Nullable>enable</Nullable>
1212
<PackageIcon>logo.png</PackageIcon>
1313
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
Lines changed: 119 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,160 @@
11
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq.Dynamic.Core.Extensions;
24
using System.Linq.Dynamic.Core.Validation;
35
using System.Reflection;
46

5-
namespace System.Linq.Dynamic.Core.CustomTypeProviders
7+
namespace System.Linq.Dynamic.Core.CustomTypeProviders;
8+
9+
/// <summary>
10+
/// The abstract DynamicLinqCustomTypeProvider which is used by the DefaultDynamicLinqCustomTypeProvider and can be used by a custom TypeProvider like in .NET Core.
11+
/// </summary>
12+
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
13+
public abstract class AbstractDynamicLinqCustomTypeProvider
614
{
715
/// <summary>
8-
/// The abstract DynamicLinqCustomTypeProvider which is used by the DefaultDynamicLinqCustomTypeProvider and can be used by a custom TypeProvider like in .NET Core.
16+
/// Finds the unique types marked with DynamicLinqTypeAttribute.
917
/// </summary>
10-
public abstract class AbstractDynamicLinqCustomTypeProvider
18+
/// <param name="assemblies">The assemblies to process.</param>
19+
/// <returns><see cref="IEnumerable{Type}" /></returns>
20+
protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
1121
{
12-
/// <summary>
13-
/// Finds the unique types marked with DynamicLinqTypeAttribute.
14-
/// </summary>
15-
/// <param name="assemblies">The assemblies to process.</param>
16-
/// <returns><see cref="IEnumerable{Type}" /></returns>
17-
protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
18-
{
19-
Check.NotNull(assemblies, nameof(assemblies));
22+
Check.NotNull(assemblies);
2023
#if !NET35
21-
assemblies = assemblies.Where(a => !a.IsDynamic);
24+
assemblies = assemblies.Where(a => !a.IsDynamic);
2225
#endif
23-
return GetAssemblyTypesWithDynamicLinqTypeAttribute(assemblies).Distinct().ToArray();
24-
}
26+
return GetAssemblyTypesWithDynamicLinqTypeAttribute(assemblies).Distinct().ToArray();
27+
}
2528

26-
/// <summary>
27-
/// Resolve any type which is registered in the current application domain.
28-
/// </summary>
29-
/// <param name="assemblies">The assemblies to inspect.</param>
30-
/// <param name="typeName">The typename to resolve.</param>
31-
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
32-
protected Type? ResolveType(IEnumerable<Assembly> assemblies, string typeName)
33-
{
34-
Check.NotNull(assemblies, nameof(assemblies));
35-
Check.NotEmpty(typeName, nameof(typeName));
29+
/// <summary>
30+
/// Resolve any type which is registered in the current application domain.
31+
/// </summary>
32+
/// <param name="assemblies">The assemblies to inspect.</param>
33+
/// <param name="typeName">The typename to resolve.</param>
34+
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
35+
protected Type? ResolveType(IEnumerable<Assembly> assemblies, string typeName)
36+
{
37+
Check.NotNull(assemblies);
38+
Check.NotEmpty(typeName);
3639

37-
foreach (var assembly in assemblies)
40+
foreach (var assembly in assemblies)
41+
{
42+
var resolvedType = assembly.GetType(typeName, false, true);
43+
if (resolvedType != null)
3844
{
39-
Type resolvedType = assembly.GetType(typeName, false, true);
40-
if (resolvedType != null)
41-
{
42-
return resolvedType;
43-
}
45+
return resolvedType;
4446
}
45-
46-
return null;
4747
}
4848

49-
/// <summary>
50-
/// Resolve a type by the simple name which is registered in the current application domain.
51-
/// </summary>
52-
/// <param name="assemblies">The assemblies to inspect.</param>
53-
/// <param name="simpleTypeName">The simple typename to resolve.</param>
54-
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
55-
protected Type? ResolveTypeBySimpleName(IEnumerable<Assembly> assemblies, string simpleTypeName)
49+
return null;
50+
}
51+
52+
/// <summary>
53+
/// Resolve a type by the simple name which is registered in the current application domain.
54+
/// </summary>
55+
/// <param name="assemblies">The assemblies to inspect.</param>
56+
/// <param name="simpleTypeName">The simple typename to resolve.</param>
57+
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
58+
protected Type? ResolveTypeBySimpleName(IEnumerable<Assembly> assemblies, string simpleTypeName)
59+
{
60+
Check.NotNull(assemblies);
61+
Check.NotEmpty(simpleTypeName);
62+
63+
foreach (var assembly in assemblies)
5664
{
57-
Check.NotNull(assemblies, nameof(assemblies));
58-
Check.NotEmpty(simpleTypeName, nameof(simpleTypeName));
65+
var fullNames = assembly.GetTypes().Select(t => t.FullName!).Distinct();
66+
var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
5967

60-
foreach (var assembly in assemblies)
68+
if (firstMatchingFullname != null)
6169
{
62-
var fullNames = assembly.GetTypes().Select(t => t.FullName!).Distinct();
63-
var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
64-
65-
if (firstMatchingFullname != null)
70+
var resolvedType = assembly.GetType(firstMatchingFullname, false, true);
71+
if (resolvedType != null)
6672
{
67-
var resolvedType = assembly.GetType(firstMatchingFullname, false, true);
68-
if (resolvedType != null)
69-
{
70-
return resolvedType;
71-
}
73+
return resolvedType;
7274
}
7375
}
74-
75-
return null;
7676
}
7777

78+
return null;
79+
}
80+
7881
#if (WINDOWS_APP || UAP10_0 || NETSTANDARD)
79-
/// <summary>
80-
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
81-
/// </summary>
82-
/// <param name="assemblies">The assemblies to process.</param>
83-
/// <returns><see cref="IEnumerable{Type}" /></returns>
84-
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
82+
/// <summary>
83+
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
84+
/// </summary>
85+
/// <param name="assemblies">The assemblies to process.</param>
86+
/// <returns><see cref="IEnumerable{Type}" /></returns>
87+
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
88+
{
89+
Check.NotNull(assemblies);
90+
91+
foreach (var assembly in assemblies)
8592
{
86-
Check.NotNull(assemblies, nameof(assemblies));
93+
var definedTypes = Type.EmptyTypes;
8794

88-
foreach (var assembly in assemblies)
95+
try
96+
{
97+
definedTypes = assembly.ExportedTypes.ToArray();
98+
}
99+
catch (ReflectionTypeLoadException reflectionTypeLoadException)
100+
{
101+
definedTypes = reflectionTypeLoadException.Types.WhereNotNull().ToArray();
102+
}
103+
catch
89104
{
90-
Type[]? definedTypes = null;
105+
// Ignore all other exceptions
106+
}
91107

92-
try
93-
{
94-
definedTypes = assembly.ExportedTypes.Where(t => t.GetTypeInfo().IsDefined(typeof(DynamicLinqTypeAttribute), false)).ToArray();
95-
}
96-
catch (ReflectionTypeLoadException reflectionTypeLoadException)
97-
{
98-
definedTypes = reflectionTypeLoadException.Types;
99-
}
100-
catch
101-
{
102-
// Ignore all other exceptions
103-
}
108+
var filteredAndDistinct = definedTypes
109+
.Where(t => t.GetTypeInfo().IsDefined(typeof(DynamicLinqTypeAttribute), false))
110+
.Distinct();
104111

105-
if (definedTypes != null && definedTypes.Length > 0)
106-
{
107-
foreach (var definedType in definedTypes)
108-
{
109-
yield return definedType;
110-
}
111-
}
112+
foreach (var definedType in filteredAndDistinct)
113+
{
114+
yield return definedType;
112115
}
113116
}
117+
}
114118
#else
115-
/// <summary>
116-
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
117-
/// </summary>
118-
/// <param name="assemblies">The assemblies to process.</param>
119-
/// <returns><see cref="IEnumerable{Type}" /></returns>
120-
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
119+
/// <summary>
120+
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
121+
/// </summary>
122+
/// <param name="assemblies">The assemblies to process.</param>
123+
/// <returns><see cref="IEnumerable{Type}" /></returns>
124+
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
125+
{
126+
Check.NotNull(assemblies);
127+
128+
#if !NET5_0_OR_GREATER
129+
assemblies = assemblies.Where(a => !a.GlobalAssemblyCache); // Skip System DLL's
130+
#endif
131+
132+
foreach (var assembly in assemblies)
121133
{
122-
Check.NotNull(assemblies, nameof(assemblies));
134+
var definedTypes = Type.EmptyTypes;
123135

124-
foreach (var assembly in assemblies.Where(a => !a.GlobalAssemblyCache)) // Skip System DLL's
136+
try
125137
{
126-
Type[]? definedTypes = null;
138+
definedTypes = assembly.GetExportedTypes().ToArray();
139+
}
140+
catch (ReflectionTypeLoadException reflectionTypeLoadException)
141+
{
142+
definedTypes = reflectionTypeLoadException.Types.WhereNotNull().ToArray();
143+
}
144+
catch
145+
{
146+
// Ignore all other exceptions
147+
}
127148

128-
try
129-
{
130-
definedTypes = assembly
131-
.GetExportedTypes()
132-
.Where(t => t.IsDefined(typeof(DynamicLinqTypeAttribute), false))
133-
.ToArray();
134-
}
135-
catch (ReflectionTypeLoadException reflectionTypeLoadException)
136-
{
137-
definedTypes = reflectionTypeLoadException.Types;
138-
}
139-
catch
140-
{
141-
// Ignore all other exceptions
142-
}
149+
var filteredAndDistinct = definedTypes
150+
.Where(t => t.IsDefined(typeof(DynamicLinqTypeAttribute), false))
151+
.Distinct();
143152

144-
if (definedTypes != null && definedTypes.Length > 0)
145-
{
146-
foreach (var definedType in definedTypes)
147-
{
148-
yield return definedType;
149-
}
150-
}
153+
foreach (var definedType in filteredAndDistinct)
154+
{
155+
yield return definedType;
151156
}
152157
}
153-
#endif
154158
}
155-
}
159+
#endif
160+
}
Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq.Dynamic.Core.Validation;
24

3-
namespace System.Linq.Dynamic.Core.Extensions
5+
namespace System.Linq.Dynamic.Core.Extensions;
6+
7+
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
8+
internal static class LinqExtensions
49
{
5-
internal static class LinqExtensions
10+
// Ex: collection.TakeLast(5);
11+
public static IEnumerable<T> TakeLast<T>(this IList<T> source, int n)
612
{
7-
// Ex: collection.TakeLast(5);
8-
public static IEnumerable<T> TakeLast<T>(this IList<T> source, int n)
9-
{
10-
return source.Skip(Math.Max(0, source.Count() - n));
11-
}
13+
return source.Skip(Math.Max(0, source.Count() - n));
14+
}
15+
16+
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> sequence)
17+
{
18+
Check.NotNull(sequence);
19+
20+
return sequence.Where(e => e != null)!;
1221
}
1322
}

0 commit comments

Comments
 (0)