Skip to content

Commit 8e79c5c

Browse files
committed
use IResourceNameFormatter in ContextGraph
add documentation
1 parent 3f0f1d9 commit 8e79c5c

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

Diff for: src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs

+22-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ public interface IContextGraphBuilder
4848
/// <typeparam name="T">The <see cref="DbContext"/> implementation type.</typeparam>
4949
IContextGraphBuilder AddDbContext<T>() where T : DbContext;
5050

51+
/// <summary>
52+
/// Specify the <see cref="IResourceNameFormatter"/> used to format resource names.
53+
/// </summary>
54+
/// <param name="resourceNameFormatter">Formatter used to define exposed resource names by convention.</param>
55+
IContextGraphBuilder UseNameFormatter(IResourceNameFormatter resourceNameFormatter);
56+
5157
/// <summary>
5258
/// Which links to include. Defaults to <see cref="Link.All"/>.
5359
/// </summary>
@@ -60,6 +66,8 @@ public class ContextGraphBuilder : IContextGraphBuilder
6066
private List<ValidationResult> _validationResults = new List<ValidationResult>();
6167

6268
private bool _usesDbContext;
69+
private IResourceNameFormatter _resourceNameFormatter = new DefaultResourceNameFormatter();
70+
6371
public Link DocumentLinks { get; set; } = Link.All;
6472

6573
public IContextGraph Build()
@@ -71,12 +79,15 @@ public IContextGraph Build()
7179
return graph;
7280
}
7381

82+
/// <inheritdoc />
7483
public IContextGraphBuilder AddResource<TResource>(string pluralizedTypeName) where TResource : class, IIdentifiable<int>
7584
=> AddResource<TResource, int>(pluralizedTypeName);
7685

86+
/// <inheritdoc />
7787
public IContextGraphBuilder AddResource<TResource, TId>(string pluralizedTypeName) where TResource : class, IIdentifiable<TId>
7888
=> AddResource(typeof(TResource), typeof(TId), pluralizedTypeName);
7989

90+
/// <inheritdoc />
8091
public IContextGraphBuilder AddResource(Type entityType, Type idType, string pluralizedTypeName)
8192
{
8293
AssertEntityIsNotAlreadyDefined(entityType);
@@ -152,6 +163,7 @@ protected virtual Type GetRelationshipType(RelationshipAttribute relation, Prope
152163

153164
private Type GetResourceDefinitionType(Type entityType) => typeof(ResourceDefinition<>).MakeGenericType(entityType);
154165

166+
/// <inheritdoc />
155167
public IContextGraphBuilder AddDbContext<T>() where T : DbContext
156168
{
157169
_usesDbContext = true;
@@ -174,14 +186,14 @@ public IContextGraphBuilder AddDbContext<T>() where T : DbContext
174186
var (isJsonApiResource, idType) = GetIdType(entityType);
175187

176188
if (isJsonApiResource)
177-
_entities.Add(GetEntity(GetResourceName(property, entityType), entityType, idType));
189+
_entities.Add(GetEntity(GetResourceNameFromDbSetProperty(property, entityType), entityType, idType));
178190
}
179191
}
180192

181193
return this;
182194
}
183195

184-
private string GetResourceName(PropertyInfo property, Type resourceType)
196+
private string GetResourceNameFromDbSetProperty(PropertyInfo property, Type resourceType)
185197
{
186198
// check the class definition first
187199
// [Resource("models"] public class Model : Identifiable { /* ... */ }
@@ -194,7 +206,7 @@ private string GetResourceName(PropertyInfo property, Type resourceType)
194206
return resourceAttribute.ResourceName;
195207

196208
// fallback to dsherized...this should actually check for a custom IResourceNameFormatter
197-
return property.Name.Dasherize();
209+
return _resourceNameFormatter.FormatResourceName(resourceType);
198210
}
199211

200212
private (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
@@ -213,5 +225,12 @@ private void AssertEntityIsNotAlreadyDefined(Type entityType)
213225
if (_entities.Any(e => e.EntityType == entityType))
214226
throw new InvalidOperationException($"Cannot add entity type {entityType} to context graph, there is already an entity of that type configured.");
215227
}
228+
229+
/// <inheritdoc />
230+
public IContextGraphBuilder UseNameFormatter(IResourceNameFormatter resourceNameFormatter)
231+
{
232+
_resourceNameFormatter = resourceNameFormatter;
233+
return this;
234+
}
216235
}
217236
}

Diff for: src/JsonApiDotNetCore/Graph/TypeLocator.cs

+47-7
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@
66

77
namespace JsonApiDotNetCore.Graph
88
{
9+
/// <summary>
10+
/// Used to locate types and facilitate auto-resource discovery
11+
/// </summary>
912
internal static class TypeLocator
1013
{
1114
private static Dictionary<Assembly, Type[]> _typeCache = new Dictionary<Assembly, Type[]>();
1215
private static Dictionary<Assembly, List<ResourceDescriptor>> _identifiableTypeCache = new Dictionary<Assembly, List<ResourceDescriptor>>();
16+
1317

18+
/// <summary>
19+
/// Determine whether or not this is a json:api resource by checking if it implements <see cref="IIdentifiable"/>.
20+
/// Returns the status and the resultant id type, either `(true, Type)` OR `(false, null)`
21+
/// </summary>
1422
public static (bool isJsonApiResource, Type idType) GetIdType(Type resourceType)
1523
{
1624
var identitifableType = GetIdentifiableIdType(resourceType);
@@ -37,6 +45,10 @@ private static Type[] GetAssemblyTypes(Assembly assembly)
3745
return types;
3846
}
3947

48+
49+
/// <summary>
50+
/// Get all implementations of <see cref="IIdentifiable"/>. in the assembly
51+
/// </summary>
4052
public static List<ResourceDescriptor> GetIdentifableTypes(Assembly assembly)
4153
{
4254
if (_identifiableTypeCache.TryGetValue(assembly, out var descriptors) == false)
@@ -55,6 +67,17 @@ public static List<ResourceDescriptor> GetIdentifableTypes(Assembly assembly)
5567
return descriptors;
5668
}
5769

70+
/// <summary>
71+
/// Get all implementations of the generic interface
72+
/// </summary>
73+
/// <param name="assembly">The assembly to search</param>
74+
/// <param name="openGenericInterfaceType">The open generic type, e.g. `typeof(IResourceService&lt;&gt;)`</param>
75+
/// <param name="genericInterfaceArguments">Parameters to the generic type</param>
76+
/// <example>
77+
/// <code>
78+
/// GetGenericInterfaceImplementation(assembly, typeof(IResourceService&lt;&gt;), typeof(Article), typeof(Guid));
79+
/// </code>
80+
/// </example>
5881
public static (Type implementation, Type registrationInterface) GetGenericInterfaceImplementation(Assembly assembly, Type openGenericInterfaceType, params Type[] genericInterfaceArguments)
5982
{
6083
foreach (var type in assembly.GetTypes())
@@ -71,16 +94,33 @@ public static (Type implementation, Type registrationInterface) GetGenericInterf
7194
return (null, null);
7295
}
7396

74-
public static IEnumerable<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, Type genericArgument)
97+
/// <summary>
98+
/// Get all derivitives of the concrete, generic type.
99+
/// </summary>
100+
/// <param name="assembly">The assembly to search</param>
101+
/// <param name="openGenericType">The open generic type, e.g. `typeof(ResourceDefinition&lt;&gt;)`</param>
102+
/// <param name="genericArguments">Parameters to the generic type</param>
103+
/// <example>
104+
/// <code>
105+
/// GetDerivedGenericTypes(assembly, typeof(ResourceDefinition<>), typeof(Article))
106+
/// </code>
107+
/// </example>
108+
public static IEnumerable<Type> GetDerivedGenericTypes(Assembly assembly, Type openGenericType, params Type[] genericArguments)
75109
{
76-
var genericType = openGenericType.MakeGenericType(genericArgument);
77-
foreach (var type in assembly.GetTypes())
78-
{
79-
if (genericType.IsAssignableFrom(type))
80-
yield return type;
81-
}
110+
var genericType = openGenericType.MakeGenericType(genericArguments);
111+
return GetDerivedTypes(assembly, genericType);
82112
}
83113

114+
/// <summary>
115+
/// Get all derivitives of the specified type.
116+
/// </summary>
117+
/// <param name="assembly">The assembly to search</param>
118+
/// <param name="openGenericType">The inherited type</param>
119+
/// <example>
120+
/// <code>
121+
/// GetDerivedGenericTypes(assembly, typeof(DbContext))
122+
/// </code>
123+
/// </example>
84124
public static IEnumerable<Type> GetDerivedTypes(Assembly assembly, Type inheritedType)
85125
{
86126
foreach (var type in assembly.GetTypes())

Diff for: src/JsonApiDotNetCore/JsonApiDotNetCore.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<VersionPrefix>2.4.0</VersionPrefix>
3+
<VersionPrefix>3.0.0</VersionPrefix>
44
<TargetFrameworks>$(NetStandardVersion)</TargetFrameworks>
55
<AssemblyName>JsonApiDotNetCore</AssemblyName>
66
<PackageId>JsonApiDotNetCore</PackageId>

0 commit comments

Comments
 (0)