/// <summary> /// Additional processing required for client deserialization, responsible /// for parsing the <see cref="Document.Included"/> property. When a relationship value is parsed, /// it goes through the included list to set its attributes and relationships. /// </summary> /// <param name="entity">The entity that was constructed from the document's body</param> /// <param name="field">The metadata for the exposed field</param> /// <param name="data">Relationship data for <paramref name="entity"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/></param> protected override void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null) { // Client deserializers do not need additional processing for attributes. if (field is AttrAttribute) { return; } // if the included property is empty or absent, there is no additional data to be parsed. if (_document.Included == null || _document.Included.Count == 0) { return; } if (field is HasOneAttribute hasOneAttr) { // add attributes and relationships of a parsed HasOne relationship var rio = data.SingleData; hasOneAttr.SetValue(entity, rio == null ? null : ParseIncludedRelationship(hasOneAttr, rio), _resourceFactory); } else if (field is HasManyAttribute hasManyAttr) { // add attributes and relationships of a parsed HasMany relationship var items = data.ManyData.Select(rio => ParseIncludedRelationship(hasManyAttr, rio)); var values = items.CopyToTypedCollection(hasManyAttr.PropertyInfo.PropertyType); hasManyAttr.SetValue(entity, values, _resourceFactory); } }
/// <summary> /// Additional processing required for client deserialization, responsible /// for parsing the <see cref="Document.Included"/> property. When a relationship value is parsed, /// it goes through the included list to set its attributes and relationships. /// </summary> /// <param name="entity">The entity that was constructed from the document's body</param> /// <param name="field">The metadata for the exposed field</param> /// <param name="data">Relationship data for <paramref name="entity"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/></param> protected override void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null) { // Client deserializers do not need additional processing for attributes. if (field is AttrAttribute) { return; } // if the included property is empty or absent, there is no additional data to be parsed. if (_document.Included == null || _document.Included.Count == 0) { return; } if (field is HasOneAttribute hasOneAttr) { // add attributes and relationships of a parsed HasOne relationship var rio = data.SingleData; hasOneAttr.SetValue(entity, rio == null ? null : ParseIncludedRelationship(hasOneAttr, rio)); } else if (field is HasManyAttribute hasManyAttr) { // add attributes and relationships of a parsed HasMany relationship var values = TypeHelper.CreateListFor(hasManyAttr.RightType); foreach (var rio in data.ManyData) { values.Add(ParseIncludedRelationship(hasManyAttr, rio)); } hasManyAttr.SetValue(entity, values); } }
/// <summary> /// Additional procesing required for server deserialization. Flags a /// processed attribute or relationship as updated using <see cref="ITargetedFields"/>. /// </summary> /// <param name="entity">The entity that was constructed from the document's body</param> /// <param name="field">The metadata for the exposed field</param> /// <param name="data">Relationship data for <paramref name="entity"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/></param> protected override void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null) { if (field is AttrAttribute attr) { if (!attr.IsImmutable) { _targetedFields.Attributes.Add(attr); } else { throw new InvalidOperationException($"Attribute {attr.PublicAttributeName} is immutable and therefore cannot be updated."); } } else if (field is RelationshipAttribute relationship) { _targetedFields.Relationships.Add(relationship); } }
/// <summary> /// Additional processing required for server deserialization. Flags a /// processed attribute or relationship as updated using <see cref="ITargetedFields"/>. /// </summary> /// <param name="entity">The entity that was constructed from the document's body</param> /// <param name="field">The metadata for the exposed field</param> /// <param name="data">Relationship data for <paramref name="entity"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/></param> protected override void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null) { if (field is AttrAttribute attr) { if (attr.Capabilities.HasFlag(AttrCapabilities.AllowMutate)) { _targetedFields.Attributes.Add(attr); } else { throw new InvalidRequestBodyException( "Changing the value of the requested attribute is not allowed.", $"Changing the value of '{attr.PublicAttributeName}' is not allowed.", null); } } else if (field is RelationshipAttribute relationship) { _targetedFields.Relationships.Add(relationship); } }
/// <summary> /// This method is called each time an <paramref name="entity"/> is constructed /// from the serialized content, which is used to do additional processing /// depending on the type of deserializers. /// </summary> /// <remarks> /// See the implementation of this method in <see cref="ResponseDeserializer"/> /// and <see cref="RequestDeserializer"/> for examples. /// </remarks> /// <param name="entity">The entity that was constructed from the document's body</param> /// <param name="field">The metadata for the exposed field</param> /// <param name="data">Relationship data for <paramref name="entity"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/></param> protected abstract void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null);
protected override void AfterProcessField(IIdentifiable entity, IResourceField field, RelationshipEntry data = null) { }