diff --git a/src/JsonApiDotNetCore/Internal/ResourceGraph.cs b/src/JsonApiDotNetCore/Internal/ResourceGraph.cs index ee056ad4c2..a39980a6ea 100644 --- a/src/JsonApiDotNetCore/Internal/ResourceGraph.cs +++ b/src/JsonApiDotNetCore/Internal/ResourceGraph.cs @@ -13,6 +13,7 @@ namespace JsonApiDotNetCore.Internal public class ResourceGraph : IResourceGraph { private List Resources { get; } + private static readonly Type proxyTargetAccessorType = Type.GetType("Castle.DynamicProxy.IProxyTargetAccessor, Castle.Core"); public ResourceGraph(List resources) { @@ -26,7 +27,9 @@ public ResourceContext GetResourceContext(string resourceName) => Resources.SingleOrDefault(e => e.ResourceName == resourceName); /// public ResourceContext GetResourceContext(Type resourceType) - => Resources.SingleOrDefault(e => e.ResourceType == resourceType); + => IsLazyLoadingProxyForResourceType(resourceType) ? + Resources.SingleOrDefault(e => e.ResourceType == resourceType.BaseType) : + Resources.SingleOrDefault(e => e.ResourceType == resourceType); /// public ResourceContext GetResourceContext() where TResource : class, IIdentifiable => GetResourceContext(typeof(TResource)); @@ -121,10 +124,13 @@ private IEnumerable Getter(Expression> selec } throw new ArgumentException( - $"The expression '{selector}' should select a single property or select multiple properties into an anonymous type. " + + $"The expression '{selector}' should select a single property or select multiple properties into an anonymous type. " + $"For example: 'article => article.Title' or 'article => new {{ article.Title, article.PageCount }}'."); } + private bool IsLazyLoadingProxyForResourceType(Type resourceType) => + proxyTargetAccessorType?.IsAssignableFrom(resourceType) ?? false; + private static Expression RemoveConvert(Expression expression) => expression is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert diff --git a/test/UnitTests/Internal/ResourceGraphBuilder_Tests.cs b/test/UnitTests/Internal/ResourceGraphBuilder_Tests.cs index 1ceb41f2aa..52186dedb9 100644 --- a/test/UnitTests/Internal/ResourceGraphBuilder_Tests.cs +++ b/test/UnitTests/Internal/ResourceGraphBuilder_Tests.cs @@ -1,9 +1,11 @@ using JsonApiDotNetCore.Builders; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Internal; +using JsonApiDotNetCore.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Castle.DynamicProxy; using Xunit; namespace UnitTests.Internal @@ -41,12 +43,47 @@ public void Adding_DbContext_Members_That_Do_Not_Implement_IIdentifiable_Logs_Wa Assert.Equal("Entity 'UnitTests.Internal.ResourceGraphBuilder_Tests+TestContext' does not implement 'IIdentifiable'.", loggerFactory.Logger.Messages[0].Text); } + [Fact] + public void GetResourceContext_Yields_Right_Type_For_LazyLoadingProxy() + { + // Arrange + var resourceGraphBuilder = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance); + resourceGraphBuilder.AddResource(); + var resourceGraph = (ResourceGraph)resourceGraphBuilder.Build(); + var proxyGenerator = new ProxyGenerator(); + + // Act + var proxy = proxyGenerator.CreateClassProxy(); + var result = resourceGraph.GetResourceContext(proxy.GetType()); + + // Assert + Assert.Equal(typeof(Bar), result.ResourceType); + } + + [Fact] + public void GetResourceContext_Yields_Right_Type_For_Identifiable() + { + // Arrange + var resourceGraphBuilder = new ResourceGraphBuilder(new JsonApiOptions(), NullLoggerFactory.Instance); + resourceGraphBuilder.AddResource(); + var resourceGraph = (ResourceGraph)resourceGraphBuilder.Build(); + + // Act + var result = resourceGraph.GetResourceContext(typeof(Bar)); + + // Assert + Assert.Equal(typeof(Bar), result.ResourceType); + } + private class Foo { } private class TestContext : DbContext { public DbSet Foos { get; set; } } + + public class Bar : Identifiable { } + } } diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj index f9c5e4b14a..b934bfee70 100644 --- a/test/UnitTests/UnitTests.csproj +++ b/test/UnitTests/UnitTests.csproj @@ -16,6 +16,7 @@ +