Skip to content

Commit 4dc1765

Browse files
author
Bart Koelman
committed
Corrected terminology for generic type usage
1 parent 8203ce6 commit 4dc1765

File tree

8 files changed

+103
-100
lines changed

8 files changed

+103
-100
lines changed

src/JsonApiDotNetCore/Configuration/JsonApiApplicationBuilder.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ public void ConfigureServiceContainer(ICollection<Type> dbContextTypes)
134134

135135
foreach (Type dbContextType in dbContextTypes)
136136
{
137-
Type dbContextResolverType = typeof(DbContextResolver<>).MakeGenericType(dbContextType);
138-
_services.AddScoped(typeof(IDbContextResolver), dbContextResolverType);
137+
Type dbContextResolverClosedType = typeof(DbContextResolver<>).MakeGenericType(dbContextType);
138+
_services.AddScoped(typeof(IDbContextResolver), dbContextResolverClosedType);
139139
}
140140

141141
_services.AddScoped<IOperationsTransactionFactory, EntityFrameworkCoreTransactionFactory>();
@@ -182,29 +182,29 @@ private void AddMiddlewareLayer()
182182

183183
private void AddResourceLayer()
184184
{
185-
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.ResourceDefinitionInterfaces, typeof(JsonApiResourceDefinition<,>));
185+
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.ResourceDefinitionOpenInterfaces, typeof(JsonApiResourceDefinition<,>));
186186

187187
_services.AddScoped<IResourceDefinitionAccessor, ResourceDefinitionAccessor>();
188188
_services.AddScoped<IResourceFactory, ResourceFactory>();
189189
}
190190

191191
private void AddRepositoryLayer()
192192
{
193-
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.RepositoryInterfaces, typeof(EntityFrameworkCoreRepository<,>));
193+
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.RepositoryOpenInterfaces, typeof(EntityFrameworkCoreRepository<,>));
194194

195195
_services.AddScoped<IResourceRepositoryAccessor, ResourceRepositoryAccessor>();
196196
}
197197

198198
private void AddServiceLayer()
199199
{
200-
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.ServiceInterfaces, typeof(JsonApiResourceService<,>));
200+
RegisterImplementationForOpenInterfaces(ServiceDiscoveryFacade.ServiceOpenInterfaces, typeof(JsonApiResourceService<,>));
201201
}
202202

203-
private void RegisterImplementationForOpenInterfaces(HashSet<Type> openGenericInterfaces, Type implementationType)
203+
private void RegisterImplementationForOpenInterfaces(HashSet<Type> openInterfaces, Type implementationType)
204204
{
205-
foreach (Type openGenericInterface in openGenericInterfaces)
205+
foreach (Type openInterface in openInterfaces)
206206
{
207-
_services.TryAddScoped(openGenericInterface, implementationType);
207+
_services.TryAddScoped(openInterface, implementationType);
208208
}
209209
}
210210

src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static IServiceCollection AddResourceService<TService>(this IServiceColle
5959
{
6060
ArgumentGuard.NotNull(services, nameof(services));
6161

62-
RegisterForConstructedType(services, typeof(TService), ServiceDiscoveryFacade.ServiceInterfaces);
62+
RegisterTypeForOpenInterfaces(services, typeof(TService), ServiceDiscoveryFacade.ServiceOpenInterfaces);
6363

6464
return services;
6565
}
@@ -72,7 +72,7 @@ public static IServiceCollection AddResourceRepository<TRepository>(this IServic
7272
{
7373
ArgumentGuard.NotNull(services, nameof(services));
7474

75-
RegisterForConstructedType(services, typeof(TRepository), ServiceDiscoveryFacade.RepositoryInterfaces);
75+
RegisterTypeForOpenInterfaces(services, typeof(TRepository), ServiceDiscoveryFacade.RepositoryOpenInterfaces);
7676

7777
return services;
7878
}
@@ -85,25 +85,25 @@ public static IServiceCollection AddResourceDefinition<TResourceDefinition>(this
8585
{
8686
ArgumentGuard.NotNull(services, nameof(services));
8787

88-
RegisterForConstructedType(services, typeof(TResourceDefinition), ServiceDiscoveryFacade.ResourceDefinitionInterfaces);
88+
RegisterTypeForOpenInterfaces(services, typeof(TResourceDefinition), ServiceDiscoveryFacade.ResourceDefinitionOpenInterfaces);
8989

9090
return services;
9191
}
9292

93-
private static void RegisterForConstructedType(IServiceCollection services, Type implementationType, IEnumerable<Type> openGenericInterfaces)
93+
private static void RegisterTypeForOpenInterfaces(IServiceCollection serviceCollection, Type implementationType, IEnumerable<Type> openInterfaces)
9494
{
9595
bool seenCompatibleInterface = false;
9696
ResourceDescriptor? resourceDescriptor = ResolveResourceTypeFromServiceImplementation(implementationType);
9797

9898
if (resourceDescriptor != null)
9999
{
100-
foreach (Type openGenericInterface in openGenericInterfaces)
100+
foreach (Type openInterface in openInterfaces)
101101
{
102-
Type constructedType = openGenericInterface.MakeGenericType(resourceDescriptor.ResourceClrType, resourceDescriptor.IdClrType);
102+
Type closedInterface = openInterface.MakeGenericType(resourceDescriptor.ResourceClrType, resourceDescriptor.IdClrType);
103103

104-
if (constructedType.IsAssignableFrom(implementationType))
104+
if (closedInterface.IsAssignableFrom(implementationType))
105105
{
106-
services.AddScoped(constructedType, implementationType);
106+
serviceCollection.AddScoped(closedInterface, implementationType);
107107
seenCompatibleInterface = true;
108108
}
109109
}
@@ -121,8 +121,8 @@ private static void RegisterForConstructedType(IServiceCollection services, Type
121121
{
122122
foreach (Type @interface in serviceType.GetInterfaces())
123123
{
124-
Type? firstGenericArgument = @interface.IsGenericType ? @interface.GenericTypeArguments.First() : null;
125-
ResourceDescriptor? resourceDescriptor = TypeLocator.ResolveResourceDescriptor(firstGenericArgument);
124+
Type? firstTypeArgument = @interface.IsGenericType ? @interface.GenericTypeArguments.First() : null;
125+
ResourceDescriptor? resourceDescriptor = TypeLocator.ResolveResourceDescriptor(firstTypeArgument);
126126

127127
if (resourceDescriptor != null)
128128
{

src/JsonApiDotNetCore/Configuration/ServiceDiscoveryFacade.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace JsonApiDotNetCore.Configuration;
1515
[PublicAPI]
1616
public sealed class ServiceDiscoveryFacade
1717
{
18-
internal static readonly HashSet<Type> ServiceInterfaces = new()
18+
internal static readonly HashSet<Type> ServiceOpenInterfaces = new()
1919
{
2020
typeof(IResourceService<,>),
2121
typeof(IResourceCommandService<,>),
@@ -32,14 +32,14 @@ public sealed class ServiceDiscoveryFacade
3232
typeof(IRemoveFromRelationshipService<,>)
3333
};
3434

35-
internal static readonly HashSet<Type> RepositoryInterfaces = new()
35+
internal static readonly HashSet<Type> RepositoryOpenInterfaces = new()
3636
{
3737
typeof(IResourceRepository<,>),
3838
typeof(IResourceWriteRepository<,>),
3939
typeof(IResourceReadRepository<,>)
4040
};
4141

42-
internal static readonly HashSet<Type> ResourceDefinitionInterfaces = new()
42+
internal static readonly HashSet<Type> ResourceDefinitionOpenInterfaces = new()
4343
{
4444
typeof(IResourceDefinition<,>)
4545
};
@@ -118,8 +118,8 @@ private void AddDbContextResolvers(Assembly assembly)
118118

119119
foreach (Type dbContextType in dbContextTypes)
120120
{
121-
Type dbContextResolverType = typeof(DbContextResolver<>).MakeGenericType(dbContextType);
122-
_services.AddScoped(typeof(IDbContextResolver), dbContextResolverType);
121+
Type dbContextResolverClosedType = typeof(DbContextResolver<>).MakeGenericType(dbContextType);
122+
_services.AddScoped(typeof(IDbContextResolver), dbContextResolverClosedType);
123123
}
124124
}
125125

@@ -130,40 +130,40 @@ private void AddResource(ResourceDescriptor resourceDescriptor)
130130

131131
private void AddServices(Assembly assembly, ResourceDescriptor resourceDescriptor)
132132
{
133-
foreach (Type serviceInterface in ServiceInterfaces)
133+
foreach (Type serviceInterface in ServiceOpenInterfaces)
134134
{
135135
RegisterImplementations(assembly, serviceInterface, resourceDescriptor);
136136
}
137137
}
138138

139139
private void AddRepositories(Assembly assembly, ResourceDescriptor resourceDescriptor)
140140
{
141-
foreach (Type repositoryInterface in RepositoryInterfaces)
141+
foreach (Type repositoryInterface in RepositoryOpenInterfaces)
142142
{
143143
RegisterImplementations(assembly, repositoryInterface, resourceDescriptor);
144144
}
145145
}
146146

147147
private void AddResourceDefinitions(Assembly assembly, ResourceDescriptor resourceDescriptor)
148148
{
149-
foreach (Type resourceDefinitionInterface in ResourceDefinitionInterfaces)
149+
foreach (Type resourceDefinitionInterface in ResourceDefinitionOpenInterfaces)
150150
{
151151
RegisterImplementations(assembly, resourceDefinitionInterface, resourceDescriptor);
152152
}
153153
}
154154

155155
private void RegisterImplementations(Assembly assembly, Type interfaceType, ResourceDescriptor resourceDescriptor)
156156
{
157-
Type[] genericArguments = interfaceType.GetTypeInfo().GenericTypeParameters.Length == 2
157+
Type[] typeArguments = interfaceType.GetTypeInfo().GenericTypeParameters.Length == 2
158158
? ArrayFactory.Create(resourceDescriptor.ResourceClrType, resourceDescriptor.IdClrType)
159159
: ArrayFactory.Create(resourceDescriptor.ResourceClrType);
160160

161-
(Type implementation, Type registrationInterface)? result = _typeLocator.GetGenericInterfaceImplementation(assembly, interfaceType, genericArguments);
161+
(Type implementationType, Type serviceInterface)? result = _typeLocator.GetContainerRegistrationFromAssembly(assembly, interfaceType, typeArguments);
162162

163163
if (result != null)
164164
{
165-
(Type implementation, Type registrationInterface) = result.Value;
166-
_services.AddScoped(registrationInterface, implementation);
165+
(Type implementationType, Type serviceInterface) = result.Value;
166+
_services.AddScoped(serviceInterface, implementationType);
167167
}
168168
}
169169
}

src/JsonApiDotNetCore/Configuration/TypeLocator.cs

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,23 @@ namespace JsonApiDotNetCore.Configuration;
88
/// </summary>
99
internal sealed class TypeLocator
1010
{
11+
// As a reminder, the following terminology is used for generic types:
12+
// non-generic string
13+
// generic
14+
// unbound Dictionary<,>
15+
// constructed
16+
// open Dictionary<TKey,TValue>
17+
// closed Dictionary<string,int>
18+
1119
/// <summary>
1220
/// Attempts to lookup the ID type of the specified resource type. Returns <c>null</c> if it does not implement <see cref="IIdentifiable{TId}" />.
1321
/// </summary>
1422
public Type? LookupIdType(Type? resourceClrType)
1523
{
16-
Type? identifiableInterface = resourceClrType?.GetInterfaces().FirstOrDefault(@interface =>
24+
Type? identifiableClosedInterface = resourceClrType?.GetInterfaces().FirstOrDefault(@interface =>
1725
@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IIdentifiable<>));
1826

19-
return identifiableInterface?.GetGenericArguments()[0];
27+
return identifiableClosedInterface?.GetGenericArguments()[0];
2028
}
2129

2230
/// <summary>
@@ -38,62 +46,62 @@ internal sealed class TypeLocator
3846
}
3947

4048
/// <summary>
41-
/// Gets all implementations of a generic interface.
49+
/// Gets the implementation type with service interface (to be registered in the IoC container) for the specified open interface and its type arguments,
50+
/// by scanning for types in the specified assembly that match the signature.
4251
/// </summary>
4352
/// <param name="assembly">
44-
/// The assembly to search in.
53+
/// The assembly to search for matching types.
4554
/// </param>
46-
/// <param name="openGenericInterface">
47-
/// The open generic interface.
55+
/// <param name="openInterface">
56+
/// The open generic interface to match against.
4857
/// </param>
49-
/// <param name="interfaceGenericTypeArguments">
50-
/// Generic type parameters to construct the generic interface.
58+
/// <param name="interfaceTypeArguments">
59+
/// Generic type arguments to construct <paramref name="openInterface" />.
5160
/// </param>
5261
/// <example>
5362
/// <code><![CDATA[
54-
/// GetGenericInterfaceImplementation(assembly, typeof(IResourceService<,>), typeof(Article), typeof(Guid));
63+
/// GetContainerRegistrationFromAssembly(assembly, typeof(IResourceService<,>), typeof(Article), typeof(Guid));
5564
/// ]]></code>
5665
/// </example>
57-
public (Type implementation, Type registrationInterface)? GetGenericInterfaceImplementation(Assembly assembly, Type openGenericInterface,
58-
params Type[] interfaceGenericTypeArguments)
66+
public (Type implementationType, Type serviceInterface)? GetContainerRegistrationFromAssembly(Assembly assembly, Type openInterface,
67+
params Type[] interfaceTypeArguments)
5968
{
6069
ArgumentGuard.NotNull(assembly, nameof(assembly));
61-
ArgumentGuard.NotNull(openGenericInterface, nameof(openGenericInterface));
62-
ArgumentGuard.NotNull(interfaceGenericTypeArguments, nameof(interfaceGenericTypeArguments));
70+
ArgumentGuard.NotNull(openInterface, nameof(openInterface));
71+
ArgumentGuard.NotNull(interfaceTypeArguments, nameof(interfaceTypeArguments));
6372

64-
if (!openGenericInterface.IsInterface || !openGenericInterface.IsGenericType || openGenericInterface != openGenericInterface.GetGenericTypeDefinition())
73+
if (!openInterface.IsInterface || !openInterface.IsGenericType || openInterface != openInterface.GetGenericTypeDefinition())
6574
{
66-
throw new ArgumentException($"Specified type '{openGenericInterface.FullName}' is not an open generic interface.", nameof(openGenericInterface));
75+
throw new ArgumentException($"Specified type '{openInterface.FullName}' is not an open generic interface.", nameof(openInterface));
6776
}
6877

69-
if (interfaceGenericTypeArguments.Length != openGenericInterface.GetGenericArguments().Length)
78+
if (interfaceTypeArguments.Length != openInterface.GetGenericArguments().Length)
7079
{
7180
throw new ArgumentException(
72-
$"Interface '{openGenericInterface.FullName}' requires {openGenericInterface.GetGenericArguments().Length} type parameters " +
73-
$"instead of {interfaceGenericTypeArguments.Length}.", nameof(interfaceGenericTypeArguments));
81+
$"Interface '{openInterface.FullName}' requires {openInterface.GetGenericArguments().Length} type arguments " +
82+
$"instead of {interfaceTypeArguments.Length}.", nameof(interfaceTypeArguments));
7483
}
7584

76-
return assembly.GetTypes().Select(type => FindGenericInterfaceImplementationForType(type, openGenericInterface, interfaceGenericTypeArguments))
85+
return assembly.GetTypes().Select(type => GetContainerRegistrationFromType(type, openInterface, interfaceTypeArguments))
7786
.FirstOrDefault(result => result != null);
7887
}
7988

80-
private static (Type implementation, Type registrationInterface)? FindGenericInterfaceImplementationForType(Type nextType, Type openGenericInterface,
81-
Type[] interfaceGenericTypeArguments)
89+
private static (Type implementationType, Type serviceInterface)? GetContainerRegistrationFromType(Type nextType, Type openInterface,
90+
Type[] interfaceTypeArguments)
8291
{
8392
if (!nextType.IsNested)
8493
{
85-
foreach (Type nextGenericInterface in nextType.GetInterfaces().Where(type => type.IsGenericType))
94+
foreach (Type nextConstructedInterface in nextType.GetInterfaces().Where(type => type.IsGenericType))
8695
{
87-
Type nextOpenGenericInterface = nextGenericInterface.GetGenericTypeDefinition();
96+
Type nextOpenInterface = nextConstructedInterface.GetGenericTypeDefinition();
8897

89-
if (nextOpenGenericInterface == openGenericInterface)
98+
if (nextOpenInterface == openInterface)
9099
{
91-
Type[] nextGenericArguments = nextGenericInterface.GetGenericArguments();
100+
Type[] nextTypeArguments = nextConstructedInterface.GetGenericArguments();
92101

93-
if (nextGenericArguments.Length == interfaceGenericTypeArguments.Length &&
94-
nextGenericArguments.SequenceEqual(interfaceGenericTypeArguments))
102+
if (nextTypeArguments.Length == interfaceTypeArguments.Length && nextTypeArguments.SequenceEqual(interfaceTypeArguments))
95103
{
96-
return (nextType, nextOpenGenericInterface.MakeGenericType(interfaceGenericTypeArguments));
104+
return (nextType, nextOpenInterface.MakeGenericType(interfaceTypeArguments));
97105
}
98106
}
99107
}
@@ -103,30 +111,30 @@ private static (Type implementation, Type registrationInterface)? FindGenericInt
103111
}
104112

105113
/// <summary>
106-
/// Gets all derivatives of the concrete, generic type.
114+
/// Scans for types in the specified assembly that derive from the specified open type.
107115
/// </summary>
108116
/// <param name="assembly">
109-
/// The assembly to search.
117+
/// The assembly to search for derived types.
110118
/// </param>
111-
/// <param name="openGenericType">
112-
/// The open generic type, e.g. `typeof(ResourceDefinition&lt;&gt;)`.
119+
/// <param name="openType">
120+
/// The open generic interface to match against.
113121
/// </param>
114-
/// <param name="genericArguments">
115-
/// Parameters to the generic type.
122+
/// <param name="typeArguments">
123+
/// Generic type arguments to construct <paramref name="openType" />.
116124
/// </param>
117125
/// <example>
118126
/// <code><![CDATA[
119-
/// GetDerivedGenericTypes(assembly, typeof(ResourceDefinition<>), typeof(Article))
127+
/// GetDerivedTypesForOpenType(assembly, typeof(ResourceDefinition<,>), typeof(Article), typeof(int))
120128
/// ]]></code>
121129
/// </example>
122-
public IReadOnlyCollection<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, params Type[] genericArguments)
130+
public IReadOnlyCollection<Type> GetDerivedTypesForOpenType(Assembly assembly, Type openType, params Type[] typeArguments)
123131
{
124132
ArgumentGuard.NotNull(assembly, nameof(assembly));
125-
ArgumentGuard.NotNull(openGenericType, nameof(openGenericType));
126-
ArgumentGuard.NotNull(genericArguments, nameof(genericArguments));
133+
ArgumentGuard.NotNull(openType, nameof(openType));
134+
ArgumentGuard.NotNull(typeArguments, nameof(typeArguments));
127135

128-
Type genericType = openGenericType.MakeGenericType(genericArguments);
129-
return GetDerivedTypes(assembly, genericType).ToArray();
136+
Type closedType = openType.MakeGenericType(typeArguments);
137+
return GetDerivedTypes(assembly, closedType).ToArray();
130138
}
131139

132140
/// <summary>
@@ -135,22 +143,22 @@ public IReadOnlyCollection<Type> GetDerivedGenericTypes(Assembly assembly, Type
135143
/// <param name="assembly">
136144
/// The assembly to search.
137145
/// </param>
138-
/// <param name="inheritedType">
146+
/// <param name="baseType">
139147
/// The inherited type.
140148
/// </param>
141149
/// <example>
142150
/// <code>
143-
/// GetDerivedGenericTypes(assembly, typeof(DbContext))
151+
/// GetDerivedTypes(assembly, typeof(DbContext))
144152
/// </code>
145153
/// </example>
146-
public IEnumerable<Type> GetDerivedTypes(Assembly assembly, Type inheritedType)
154+
public IEnumerable<Type> GetDerivedTypes(Assembly assembly, Type baseType)
147155
{
148156
ArgumentGuard.NotNull(assembly, nameof(assembly));
149-
ArgumentGuard.NotNull(inheritedType, nameof(inheritedType));
157+
ArgumentGuard.NotNull(baseType, nameof(baseType));
150158

151159
foreach (Type type in assembly.GetTypes())
152160
{
153-
if (inheritedType.IsAssignableFrom(type))
161+
if (baseType.IsAssignableFrom(type))
154162
{
155163
yield return type;
156164
}

0 commit comments

Comments
 (0)