Skip to content

Commit 30f11c6

Browse files
committed
generic reflector
1 parent 4087b1f commit 30f11c6

File tree

5 files changed

+171
-0
lines changed

5 files changed

+171
-0
lines changed

Diff for: src/JsonApiDotNetCore/Reflection/GenericReflector.cs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
3+
namespace JsonApiDotNetCore.Reflection
4+
{
5+
public static class GenericReflector
6+
{
7+
/// <summary>
8+
/// Gets an inherited generic argument.
9+
/// </summary>
10+
///
11+
/// <example>
12+
/// Consider `ArticlesController : JsonApiController{Article}`:
13+
///
14+
/// var result = GenericReflector.GetInheritedGenericType(typeof(ArticlesController), typeof(JsonApiController<>))
15+
///
16+
/// // result will be the `Article` type.
17+
/// </example>
18+
public static Type GetInheritedGenericType(Type derivedType, Type openGenericBaseType, int genericArgumentIndex = 0)
19+
{
20+
var baseType = derivedType.BaseType;
21+
while (baseType != null)
22+
{
23+
if (baseType.IsGenericType)
24+
{
25+
var genericTypeDefinition = baseType.GetGenericTypeDefinition();
26+
if (openGenericBaseType.IsAssignableFrom(genericTypeDefinition))
27+
{
28+
var genericArguments = baseType.GetGenericArguments();
29+
if (genericArguments.Length > genericArgumentIndex)
30+
return genericArguments[genericArgumentIndex];
31+
}
32+
}
33+
34+
// it's possible that we have several levels of inheritence
35+
// e.g. ArticleController1 : ArticleController2 : JsonApiController<Article>
36+
baseType = baseType.BaseType;
37+
}
38+
39+
return null;
40+
}
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using JsonApiDotNetCore.Internal;
2+
using Microsoft.AspNetCore.Mvc.Filters;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace JsonApiDotNetCore.Services
6+
{
7+
public class ControllerContextActionFilter : IActionFilter
8+
{
9+
private readonly IControllerContext _controllerContext;
10+
private readonly IContextGraph _contextGraph;
11+
private readonly ILogger<ControllerContextActionFilter> _logger;
12+
13+
public ControllerContextActionFilter(
14+
IControllerContext controllerContext,
15+
IContextGraph contextGraph,
16+
ILogger<ControllerContextActionFilter> logger)
17+
{
18+
_controllerContext = controllerContext;
19+
_contextGraph = contextGraph;
20+
_logger = logger;
21+
}
22+
23+
public void OnActionExecuted(ActionExecutedContext context)
24+
{
25+
throw new System.NotImplementedException();
26+
}
27+
28+
public void OnActionExecuting(ActionExecutingContext context)
29+
{
30+
// var controller = context.Controller;
31+
32+
// if (controller == null)
33+
// throw new JsonApiException(500, $"Cannot ApplyContext from null controller for type {typeof(T)}");
34+
35+
// if (controller == null)
36+
// throw new JsonApiException(500, $"Cannot ApplyContext from null controller for type {typeof(T)}");
37+
38+
// _controllerContext.ControllerType = controller.GetType();
39+
// _controllerContext.RequestEntity = _contextGraph.GetContextEntity(typeof(T));
40+
41+
// if (_controllerContext.RequestEntity == null)
42+
// throw new JsonApiException(500, $"A resource has not been properly defined for type '{typeof(T)}'. Ensure it has been registered on the ContextGraph.");
43+
}
44+
45+
// private Type GetResourceType(Type controllerType)
46+
// {
47+
// var interfaces = controllerType.GetInterfaces();
48+
// var jsonApiControllerOpenGeneric = typeof(BaseJsonApiController<,>);
49+
// foreach (var @interface in interfaces)
50+
// {
51+
52+
// if (@interface.IsGenericType && jsonApiControllerOpenGeneric.IsAssignableFrom(@interface))
53+
// {
54+
55+
// }
56+
// }
57+
// }
58+
59+
// private ContextEntity GetRequestEntity(Type controllerType)
60+
// {
61+
// var controllerGenericArguments = controllerType.GetGenericArguments();
62+
// if (controllerGenericArguments.Length == 0)
63+
// {
64+
// // TODO: are there any use-cases that this will fail on?
65+
// // e.g. ArticlesController :
66+
// _logger.LogDebug($"Cannot determine the requested resource. Controller {controllerType} does not have any generic parameters.");
67+
// return null;
68+
// }
69+
// }
70+
}
71+
}

Diff for: src/JsonApiDotNetCore/Services/IJsonApiContext.cs

+9
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,16 @@ public interface IQueryRequest
2525

2626
public interface IUpdateRequest
2727
{
28+
/// <summary>
29+
/// The attributes that were included in a PATCH request.
30+
/// Only the attributes in this dictionary should be updated.
31+
/// </summary>
2832
Dictionary<AttrAttribute, object> AttributesToUpdate { get; set; }
33+
34+
/// <summary>
35+
/// Any relationships that were included in a PATCH request.
36+
/// Only the relationships in this dictionary should be updated.
37+
/// </summary>
2938
Dictionary<RelationshipAttribute, object> RelationshipsToUpdate { get; set; }
3039
}
3140

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace JsonApiDotNetCore.Services
2+
{
3+
public class ResourceControllersMap
4+
{
5+
6+
}
7+
}

Diff for: test/UnitTests/Reflection/GenericReflector_Tests.cs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using JsonApiDotNetCore.Controllers;
3+
using JsonApiDotNetCore.Models;
4+
using JsonApiDotNetCore.Reflection;
5+
using JsonApiDotNetCore.Services;
6+
using Microsoft.Extensions.Logging;
7+
using Xunit;
8+
9+
namespace UnitTests.Reflection
10+
{
11+
public class GenericReflector_Tests
12+
{
13+
[Theory]
14+
[InlineData(typeof(Controller), typeof(JsonApiController<>), typeof(Resource))]
15+
[InlineData(typeof(Controller), typeof(JsonApiController<,>), typeof(Resource))]
16+
// [InlineData(typeof(Controller), typeof(BaseJsonApiController<>), typeof(Resource))]
17+
[InlineData(typeof(Controller), typeof(BaseJsonApiController<,>), typeof(Resource))]
18+
public void GetInheritedGenericType_Gets_ResourceType_From_Controller(Type controllerType, Type openGenericType, Type expectedResult)
19+
{
20+
// act
21+
var result = GenericReflector.GetInheritedGenericType(controllerType, openGenericType);
22+
23+
// assert
24+
Assert.Equal(expectedResult, result);
25+
}
26+
27+
public class Controller2 : Controller
28+
{
29+
public Controller2(IJsonApiContext jsonApiContext, IResourceService<Resource> resourceService, ILoggerFactory loggerFactory)
30+
: base(jsonApiContext, resourceService, loggerFactory) { }
31+
}
32+
33+
34+
public class Controller : JsonApiController<Resource>
35+
{
36+
public Controller(IJsonApiContext jsonApiContext, IResourceService<Resource> resourceService, ILoggerFactory loggerFactory)
37+
: base(jsonApiContext, resourceService, loggerFactory) { }
38+
}
39+
40+
public class Resource : Identifiable { }
41+
}
42+
}

0 commit comments

Comments
 (0)