Skip to content

Commit a8ec37f

Browse files
authored
Merge pull request #328 from json-api-dotnet/fix/#241
fix(AttrAttribute): unexpected scenarios cause breaking change
2 parents 8afd613 + 95c699d commit a8ec37f

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

Diff for: Build.ps1

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ If($env:APPVEYOR_REPO_TAG -eq $true) {
4646

4747
IF ([string]::IsNullOrWhitespace($revision)){
4848
Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts"
49-
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts
49+
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --include-symbols
5050
CheckLastExitCode
5151
}
5252
Else {
5353
Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision"
54-
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision
54+
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=$revision --include-symbols
5555
CheckLastExitCode
5656
}
5757
}
5858
Else {
5959
Write-Output "VERSION-SUFFIX: alpha1-$revision"
6060
Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision"
61-
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision
61+
dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision --include-symbols
6262
CheckLastExitCode
6363
}

Diff for: src/JsonApiDotNetCore/Models/AttrAttribute.cs

+42-3
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,54 @@ public AttrAttribute(string publicName, string internalName, bool isImmutable =
8080
/// Returns null if the attribute does not belong to the
8181
/// provided object.
8282
/// </summary>
83-
public object GetValue(object entity) => PropertyInfo.GetValue(entity);
83+
public object GetValue(object entity)
84+
{
85+
if (entity == null)
86+
throw new InvalidOperationException("Cannot GetValue from null object.");
87+
88+
var prop = GetResourceProperty(entity);
89+
return prop?.GetValue(entity);
90+
}
8491

8592
/// <summary>
8693
/// Sets the value of the attribute on the given object.
8794
/// </summary>
8895
public void SetValue(object entity, object newValue)
8996
{
90-
var convertedValue = TypeHelper.ConvertType(newValue, PropertyInfo.PropertyType);
91-
PropertyInfo.SetValue(entity, convertedValue);
97+
if (entity == null)
98+
throw new InvalidOperationException("Cannot SetValue on null object.");
99+
100+
var prop = GetResourceProperty(entity);
101+
if(prop != null)
102+
{
103+
var convertedValue = TypeHelper.ConvertType(newValue, prop.PropertyType);
104+
prop.SetValue(entity, convertedValue);
105+
}
106+
}
107+
108+
private PropertyInfo GetResourceProperty(object resource)
109+
{
110+
// There are some scenarios, especially ones where users are using a different
111+
// data model than view model, where they may use a repository implmentation
112+
// that does not match the deserialized type. For now, we will continue to support
113+
// this use case.
114+
var targetType = resource.GetType();
115+
if (targetType != PropertyInfo.DeclaringType)
116+
{
117+
var propertyInfo = resource
118+
.GetType()
119+
.GetProperty(InternalAttributeName);
120+
121+
return propertyInfo;
122+
123+
// TODO: this should throw but will be a breaking change in some cases
124+
//if (propertyInfo == null)
125+
// throw new InvalidOperationException(
126+
// $"'{targetType}' does not contain a member named '{InternalAttributeName}'." +
127+
// $"There is also a mismatch in target types. Expected '{PropertyInfo.DeclaringType}' but instead received '{targetType}'.");
128+
}
129+
130+
return PropertyInfo;
92131
}
93132

94133
/// <summary>

Diff for: src/JsonApiDotNetCore/Models/ResourceDefinition.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ protected List<AttrAttribute> Remove(Expression<Func<T, dynamic>> filter, List<A
5555
// model => model.Attribute
5656
if (filter.Body is MemberExpression memberExpression)
5757
return _contextEntity.Attributes
58-
.Where(a => a.PropertyInfo.Name != memberExpression.Member.Name)
58+
.Where(a => a.InternalAttributeName != memberExpression.Member.Name)
5959
.ToList();
6060

6161
// model => new { model.Attribute1, model.Attribute2 }
6262
if (filter.Body is NewExpression newExpression)
6363
{
6464
var attributes = new List<AttrAttribute>();
6565
foreach (var attr in _contextEntity.Attributes)
66-
if (newExpression.Members.Any(m => m.Name == attr.PropertyInfo.Name) == false)
66+
if (newExpression.Members.Any(m => m.Name == attr.InternalAttributeName) == false)
6767
attributes.Add(attr);
6868

6969
return attributes;

Diff for: src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private object SetEntityAttributes(
147147
if (attributeValues.TryGetValue(attr.PublicAttributeName, out object newValue))
148148
{
149149
var convertedValue = ConvertAttrValue(newValue, attr.PropertyInfo.PropertyType);
150-
attr.PropertyInfo.SetValue(entity, convertedValue);
150+
attr.SetValue(entity, convertedValue);
151151

152152
if (attr.IsImmutable == false)
153153
_jsonApiContext.AttributesToUpdate[attr] = convertedValue;

0 commit comments

Comments
 (0)