Skip to content

Commit e0270bd

Browse files
authored
fix: support for lazy loading proxies (#793)
fix: support for lazy loading proxies
1 parent 9d7614f commit e0270bd

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/JsonApiDotNetCore/Internal/ResourceGraph.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace JsonApiDotNetCore.Internal
1313
public class ResourceGraph : IResourceGraph
1414
{
1515
private List<ResourceContext> Resources { get; }
16+
private static readonly Type proxyTargetAccessorType = Type.GetType("Castle.DynamicProxy.IProxyTargetAccessor, Castle.Core");
1617

1718
public ResourceGraph(List<ResourceContext> resources)
1819
{
@@ -26,7 +27,9 @@ public ResourceContext GetResourceContext(string resourceName)
2627
=> Resources.SingleOrDefault(e => e.ResourceName == resourceName);
2728
/// <inheritdoc />
2829
public ResourceContext GetResourceContext(Type resourceType)
29-
=> Resources.SingleOrDefault(e => e.ResourceType == resourceType);
30+
=> IsLazyLoadingProxyForResourceType(resourceType) ?
31+
Resources.SingleOrDefault(e => e.ResourceType == resourceType.BaseType) :
32+
Resources.SingleOrDefault(e => e.ResourceType == resourceType);
3033
/// <inheritdoc />
3134
public ResourceContext GetResourceContext<TResource>() where TResource : class, IIdentifiable
3235
=> GetResourceContext(typeof(TResource));
@@ -121,10 +124,13 @@ private IEnumerable<IResourceField> Getter<T>(Expression<Func<T, dynamic>> selec
121124
}
122125

123126
throw new ArgumentException(
124-
$"The expression '{selector}' should select a single property or select multiple properties into an anonymous type. " +
127+
$"The expression '{selector}' should select a single property or select multiple properties into an anonymous type. " +
125128
$"For example: 'article => article.Title' or 'article => new {{ article.Title, article.PageCount }}'.");
126129
}
127130

131+
private bool IsLazyLoadingProxyForResourceType(Type resourceType) =>
132+
proxyTargetAccessorType?.IsAssignableFrom(resourceType) ?? false;
133+
128134
private static Expression RemoveConvert(Expression expression)
129135
=> expression is UnaryExpression unaryExpression
130136
&& unaryExpression.NodeType == ExpressionType.Convert

test/UnitTests/Internal/ResourceGraphBuilder_Tests.cs

+37
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using JsonApiDotNetCore.Builders;
22
using JsonApiDotNetCore.Configuration;
33
using JsonApiDotNetCore.Internal;
4+
using JsonApiDotNetCore.Models;
45
using Microsoft.EntityFrameworkCore;
56
using Microsoft.Extensions.Logging;
67
using Microsoft.Extensions.Logging.Abstractions;
8+
using Castle.DynamicProxy;
79
using Xunit;
810

911
namespace UnitTests.Internal
@@ -41,12 +43,47 @@ public void Adding_DbContext_Members_That_Do_Not_Implement_IIdentifiable_Logs_Wa
4143
Assert.Equal("Entity 'UnitTests.Internal.ResourceGraphBuilder_Tests+TestContext' does not implement 'IIdentifiable'.", loggerFactory.Logger.Messages[0].Text);
4244
}
4345

46+
[Fact]
47+
public void GetResourceContext_Yields_Right_Type_For_LazyLoadingProxy()
48+
{
49+
// Arrange
50+
var resourceGraphBuilder = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance);
51+
resourceGraphBuilder.AddResource<Bar>();
52+
var resourceGraph = (ResourceGraph)resourceGraphBuilder.Build();
53+
var proxyGenerator = new ProxyGenerator();
54+
55+
// Act
56+
var proxy = proxyGenerator.CreateClassProxy<Bar>();
57+
var result = resourceGraph.GetResourceContext(proxy.GetType());
58+
59+
// Assert
60+
Assert.Equal(typeof(Bar), result.ResourceType);
61+
}
62+
63+
[Fact]
64+
public void GetResourceContext_Yields_Right_Type_For_Identifiable()
65+
{
66+
// Arrange
67+
var resourceGraphBuilder = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance);
68+
resourceGraphBuilder.AddResource<Bar>();
69+
var resourceGraph = (ResourceGraph)resourceGraphBuilder.Build();
70+
71+
// Act
72+
var result = resourceGraph.GetResourceContext(typeof(Bar));
73+
74+
// Assert
75+
Assert.Equal(typeof(Bar), result.ResourceType);
76+
}
77+
4478
private class Foo { }
4579

4680
private class TestContext : DbContext
4781
{
4882
public DbSet<Foo> Foos { get; set; }
4983
}
84+
85+
public class Bar : Identifiable { }
86+
5087
}
5188

5289
}

test/UnitTests/UnitTests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<ItemGroup>
1717
<PackageReference Include="Bogus" Version="$(BogusVersion)" />
1818
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(EFCoreVersion)" />
19+
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="$(EFCoreVersion)" />
1920
<PackageReference Include="Moq" Version="$(MoqVersion)" />
2021
<PackageReference Include="xunit" Version="$(XUnitVersion)" />
2122
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitVersion)" />

0 commit comments

Comments
 (0)