public static object GetTypedId(this IIdentifiable identifiable) { ArgumentGuard.NotNull(identifiable, nameof(identifiable)); PropertyInfo property = identifiable.GetType().GetProperty(nameof(Identifiable.Id)); if (property == null) { throw new InvalidOperationException($"Resource of type '{identifiable.GetType()}' does not have an 'Id' property."); } return(property.GetValue(identifiable)); }
private ResourceObject GetIncludedEntity(IIdentifiable entity) { if (entity == null) { return(null); } var contextEntity = _jsonApiContext.ResourceGraph.GetContextEntity(entity.GetType()); var resourceDefinition = _scopedServiceProvider.GetService(contextEntity.ResourceType) as IResourceDefinition; var data = GetData(contextEntity, entity, resourceDefinition); data.Attributes = new Dictionary <string, object>(); foreach (var attr in contextEntity.Attributes) { if (attr.InternalAttributeName == nameof(Identifiable.Id)) { continue; } data.Attributes.Add(attr.PublicAttributeName, attr.GetValue(entity)); } return(data); }
private ResourceObject TryGetBuiltResourceObjectFor(IIdentifiable resource) { Type resourceType = resource.GetType(); ResourceContext resourceContext = ResourceContextProvider.GetResourceContext(resourceType); return(_included.SingleOrDefault(resourceObject => resourceObject.Type == resourceContext.PublicName && resourceObject.Id == resource.StringId)); }
private ResourceObject GetIncludedEntity(IIdentifiable entity, RelationshipAttribute relationship) { if (entity == null) { return(null); } var contextEntity = _jsonApiContext.ResourceGraph.GetContextEntity(entity.GetType()); var resourceDefinition = _scopedServiceProvider.GetService(contextEntity.ResourceType) as IResourceDefinition; var data = GetData(contextEntity, entity, resourceDefinition); data.Attributes = new Dictionary <string, object>(); contextEntity.Attributes.ForEach(attr => { var attributeValue = attr.GetValue(entity); if (ShouldIncludeAttribute(attr, attributeValue, relationship)) { data.Attributes.Add(attr.PublicAttributeName, attributeValue); } }); return(data); }
/// <inheritdoc /> public virtual ResourceObject Build(IIdentifiable resource, IReadOnlyCollection <AttrAttribute> attributes = null, IReadOnlyCollection <RelationshipAttribute> relationships = null) { ArgumentGuard.NotNull(resource, nameof(resource)); var resourceContext = ResourceContextProvider.GetResourceContext(resource.GetType()); // populating the top-level "type" and "id" members. var resourceObject = new ResourceObject { Type = resourceContext.PublicName, Id = resource.StringId }; // populating the top-level "attribute" member of a resource object. never include "id" as an attribute if (attributes != null) { var attributesWithoutId = attributes.Where(attr => attr.Property.Name != nameof(Identifiable.Id)).ToArray(); if (attributesWithoutId.Any()) { ProcessAttributes(resource, attributesWithoutId, resourceObject); } } // populating the top-level "relationship" member of a resource object. if (relationships != null) { ProcessRelationships(resource, relationships, resourceObject); } return(resourceObject); }
/// <inheritdoc /> public virtual ResourceObject Build(IIdentifiable resource, IReadOnlyCollection <AttrAttribute> attributes = null, IReadOnlyCollection <RelationshipAttribute> relationships = null) { if (resource == null) { throw new ArgumentNullException(nameof(resource)); } var resourceContext = ResourceContextProvider.GetResourceContext(resource.GetType()); // populating the top-level "type" and "id" members. var resourceObject = new ResourceObject { Type = resourceContext.PublicName, Id = resource.StringId == string.Empty ? null : resource.StringId }; // populating the top-level "attribute" member of a resource object. never include "id" as an attribute if (attributes != null && (attributes = attributes.Where(attr => attr.Property.Name != nameof(Identifiable.Id)).ToArray()).Any()) { ProcessAttributes(resource, attributes, resourceObject); } // populating the top-level "relationship" member of a resource object. if (relationships != null) { ProcessRelationships(resource, relationships, resourceObject); } return(resourceObject); }
/// <inheritdoc /> public string Serialize(IReadOnlyCollection <IIdentifiable> resources) { if (resources == null) { throw new ArgumentNullException(nameof(resources)); } IIdentifiable firstResource = resources.FirstOrDefault(); Document document; if (firstResource == null) { document = Build(resources, Array.Empty <AttrAttribute>(), Array.Empty <RelationshipAttribute>()); } else { _currentTargetedResource = firstResource.GetType(); var attributes = GetAttributesToSerialize(firstResource); document = Build(resources, attributes, RelationshipsToSerialize); _currentTargetedResource = null; } return(SerializeObject(document, _jsonSerializerSettings)); }
/// <inheritdoc /> public RelationshipLinks GetRelationshipLinks(RelationshipAttribute relationship, IIdentifiable parent) { ArgumentGuard.NotNull(relationship, nameof(relationship)); ArgumentGuard.NotNull(parent, nameof(parent)); ResourceContext parentResourceContext = _provider.GetResourceContext(parent.GetType()); string childNavigation = relationship.PublicName; RelationshipLinks links = null; if (ShouldAddRelationshipLink(parentResourceContext, relationship, LinkTypes.Related)) { links = new RelationshipLinks { Related = GetRelatedRelationshipLink(parentResourceContext.PublicName, parent.StringId, childNavigation) }; } if (ShouldAddRelationshipLink(parentResourceContext, relationship, LinkTypes.Self)) { links ??= new RelationshipLinks(); links.Self = GetSelfRelationshipLink(parentResourceContext.PublicName, parent.StringId, childNavigation); } return(links); }
/// <summary> /// Sets the relationships on a parsed entity /// </summary> /// <param name="entity">The parsed entity</param> /// <param name="relationshipsValues">Relationships and their values, as in the serialized content</param> /// <param name="relationshipAttributes">Exposed relationships for <paramref name="entity"/></param> /// <returns></returns> protected IIdentifiable SetRelationships(IIdentifiable entity, Dictionary <string, RelationshipEntry> relationshipsValues, List <RelationshipAttribute> relationshipAttributes) { if (relationshipsValues == null || relationshipsValues.Count == 0) { return(entity); } var entityProperties = entity.GetType().GetProperties(); foreach (var attr in relationshipAttributes) { if (!relationshipsValues.TryGetValue(attr.PublicRelationshipName, out RelationshipEntry relationshipData) || !relationshipData.IsPopulated) { continue; } if (attr is HasOneAttribute hasOneAttribute) { SetHasOneRelationship(entity, entityProperties, hasOneAttribute, relationshipData); } else { SetHasManyRelationship(entity, (HasManyAttribute)attr, relationshipData); } } return(entity); }
/// <inheritdoc /> public RelationshipLinks GetRelationshipLinks(RelationshipAttribute relationship, IIdentifiable parent) { if (relationship == null) { throw new ArgumentNullException(nameof(relationship)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } var parentResourceContext = _provider.GetResourceContext(parent.GetType()); var childNavigation = relationship.PublicName; RelationshipLinks links = null; if (ShouldAddRelationshipLink(parentResourceContext, relationship, LinkTypes.Related)) { links = new RelationshipLinks { Related = GetRelatedRelationshipLink(parentResourceContext.PublicName, parent.StringId, childNavigation) }; } if (ShouldAddRelationshipLink(parentResourceContext, relationship, LinkTypes.Self)) { links ??= new RelationshipLinks(); links.Self = GetSelfRelationshipLink(parentResourceContext.PublicName, parent.StringId, childNavigation); } return(links); }
private void DeclareLocalId(IIdentifiable resource) { if (resource.LocalId != null) { var resourceContext = _resourceContextProvider.GetResourceContext(resource.GetType()); _localIdTracker.Declare(resource.LocalId, resourceContext.PublicName); } }
private void AssertLocalIdIsAssigned(IIdentifiable resource) { if (resource.LocalId != null) { var resourceContext = _resourceContextProvider.GetResourceContext(resource.GetType()); _localIdTracker.GetValue(resource.LocalId, resourceContext.PublicName); } }
/// <inheritdoc /> public void OnSerialize(IIdentifiable resource) { ArgumentGuard.NotNull(resource, nameof(resource)); dynamic resourceDefinition = ResolveResourceDefinition(resource.GetType()); resourceDefinition.OnSerialize((dynamic)resource); }
/// <inheritdoc /> public override ResourceObject Build(IIdentifiable resource, IReadOnlyCollection <AttrAttribute> attributes = null, IReadOnlyCollection <RelationshipAttribute> relationships = null) { ResourceObject resourceObject = base.Build(resource, attributes, relationships); resourceObject.Meta = _resourceDefinitionAccessor.GetMeta(resource.GetType(), resource); return(resourceObject); }
/// <summary> /// Creates a <see cref="ResourceIdentifierObject"/> from <paramref name="resource"/>. /// </summary> private ResourceIdentifierObject GetResourceIdentifier(IIdentifiable resource) { var resourceName = ResourceContextProvider.GetResourceContext(resource.GetType()).PublicName; return(new ResourceIdentifierObject { Type = resourceName, Id = resource.StringId }); }
/// <summary> /// Creates a <see cref="ResourceIdentifierObject"/> from <paramref name="entity"/>. /// </summary> private ResourceIdentifierObject GetResourceIdentifier(IIdentifiable entity) { var resourceName = _provider.GetResourceContext(entity.GetType()).ResourceName; return(new ResourceIdentifierObject { Type = resourceName, Id = entity.StringId }); }
/// <summary> /// Adds or updates (if already exists) an entity, keyed by type and id. /// </summary> /// <param name="entity">The item to be added or updated.</param> /// <remarks> /// Not a thread-safe method. /// </remarks> internal void AddOrUpdate(IIdentifiable entity) { Type type = entity.GetType(); if (!this.supplementalData.ContainsKey(type)) { this.supplementalData.Add(type, new Dictionary <long, IIdentifiable>()); } this.supplementalData[type][entity.Id] = entity; }
public Document Build(IIdentifiable entity) { var contextEntity = _contextGraph.GetContextEntity(entity.GetType()); var document = new Document { Data = _getData(contextEntity, entity) }; return(document); }
/// <summary> /// Checks if the to-one relationship is required by checking if the foreign key is nullable. /// </summary> private bool IsRequiredToOneRelationship(HasOneAttribute attr, IIdentifiable entity) { var foreignKey = entity.GetType().GetProperty(attr.IdentifiablePropertyName); if (foreignKey != null && Nullable.GetUnderlyingType(foreignKey.PropertyType) == null) { return(true); } return(false); }
private void AssertTransactional <T>(IIdentifiable <T> item) { Assert.IsTrue(Factory.IsProxy(item.GetType())); Assert.Throws <InvalidOperationException>(() => item.Id = default(T)); bool detectable = false; using (Shield.WhenCommitting <IIdentifiable <T> >(ts => detectable = true)) Shield.InTransaction(() => item.Id = default(T)); Assert.IsTrue(detectable); }
/// <summary> /// Searches the change tracker for an entity that matches the type and ID of <paramref name="identifiable" />. /// </summary> public static object GetTrackedIdentifiable(this DbContext dbContext, IIdentifiable identifiable) { ArgumentGuard.NotNull(dbContext, nameof(dbContext)); ArgumentGuard.NotNull(identifiable, nameof(identifiable)); Type resourceType = identifiable.GetType(); string stringId = identifiable.StringId; EntityEntry entityEntry = dbContext.ChangeTracker.Entries().FirstOrDefault(entry => IsResource(entry, resourceType, stringId)); return(entityEntry?.Entity); }
private ResourceObject BuildCachedResourceObjectFor(IIdentifiable resource) { Type resourceType = resource.GetType(); IReadOnlyCollection <AttrAttribute> attributes = _fieldsToSerialize.GetAttributes(resourceType); IReadOnlyCollection <RelationshipAttribute> relationships = _fieldsToSerialize.GetRelationships(resourceType); ResourceObject resourceObject = Build(resource, attributes, relationships); _included.Add(resourceObject); return(resourceObject); }
/// <inheritdoc/> public string Serialize(IIdentifiable entity) { if (entity == null) { return(JsonConvert.SerializeObject(Build(entity, new List <AttrAttribute>(), new List <RelationshipAttribute>()))); } _currentTargetedResource = entity?.GetType(); var document = Build(entity, GetAttributesToSerialize(entity), GetRelationshipsToSerialize(entity)); _currentTargetedResource = null; return(JsonConvert.SerializeObject(document)); }
/// <summary> /// Gets the resource object for <paramref name="parent"/> by searching the included list. /// If it was not already build, it is constructed and added to the included list. /// </summary> /// <param name="parent"></param> /// <param name="relationship"></param> /// <returns></returns> private ResourceObject GetOrBuildResourceObject(IIdentifiable parent, RelationshipAttribute relationship) { var type = parent.GetType(); var resourceName = _provider.GetResourceContext(type).ResourceName; var entry = _included.SingleOrDefault(ro => ro.Type == resourceName && ro.Id == parent.StringId); if (entry == null) { entry = Build(parent, _fieldsToSerialize.GetAllowedAttributes(type, relationship), _fieldsToSerialize.GetAllowedRelationships(type)); _included.Add(entry); } return(entry); }
/// <summary> /// By default, the client serializer does not include any relationships /// for resources in the primary data unless explicitly included using /// <see cref="RelationshipsToSerialize"/>. /// </summary> private IReadOnlyCollection <RelationshipAttribute> GetRelationshipsToSerialize(IIdentifiable resource) { var currentResourceType = resource.GetType(); // only allow relationship attributes to be serialized if they were set using // <see cref="RelationshipsToInclude{T}(Expression{Func{T, dynamic}})"/> // and the current resource is a primary entry. if (RelationshipsToSerialize == null) { return(_resourceGraph.GetRelationships(currentResourceType)); } return(RelationshipsToSerialize); }
/// <summary> /// By default, the client serializer does not include any relationships /// for entities in the primary data unless explicitly included using /// <see cref="RelationshipsToSerialize"/>. /// </summary> private List <RelationshipAttribute> GetRelationshipsToSerialize(IIdentifiable entity) { var currentResourceType = entity.GetType(); // only allow relationship attributes to be serialized if they were set using // <see cref="RelationshipsToInclude{T}(Expression{Func{T, dynamic}})"/> // and the current <paramref name="entity"/> is a main entry in the primary data. if (RelationshipsToSerialize == null) { return(_resourceGraph.GetRelationships(currentResourceType)); } return(RelationshipsToSerialize.ToList()); }
/// <summary> /// Gets the resource object for <paramref name="parent" /> by searching the included list. If it was not already built, it is constructed and added to /// the inclusion list. /// </summary> private ResourceObject GetOrBuildResourceObject(IIdentifiable parent) { Type type = parent.GetType(); string resourceName = ResourceContextProvider.GetResourceContext(type).PublicName; ResourceObject entry = _included.SingleOrDefault(ro => ro.Type == resourceName && ro.Id == parent.StringId); if (entry == null) { entry = Build(parent, _fieldsToSerialize.GetAttributes(type), _fieldsToSerialize.GetRelationships(type)); _included.Add(entry); } return(entry); }
public Document Build(IIdentifiable entity) { var contextEntity = _contextGraph.GetContextEntity(entity.GetType()); var document = new Document { Data = GetData(contextEntity, entity), Meta = GetMeta(entity), Links = _jsonApiContext.PageManager.GetPageLinks(new LinkBuilder(_jsonApiContext)) }; document.Included = AppendIncludedObject(document.Included, contextEntity, entity); return(document); }
/// <inheritdoc /> public string Serialize(IIdentifiable resource) { if (resource == null) { Document empty = Build((IIdentifiable)null, Array.Empty <AttrAttribute>(), Array.Empty <RelationshipAttribute>()); return(SerializeObject(empty, _jsonSerializerSettings)); } _currentTargetedResource = resource.GetType(); Document document = Build(resource, GetAttributesToSerialize(resource), RelationshipsToSerialize); _currentTargetedResource = null; return(SerializeObject(document, _jsonSerializerSettings)); }
/// <inheritdoc/> public string Serialize(IIdentifiable entity) { if (entity == null) { var empty = Build((IIdentifiable)null, Array.Empty <AttrAttribute>(), Array.Empty <RelationshipAttribute>()); return(SerializeObject(empty, _jsonSerializerSettings)); } _currentTargetedResource = entity.GetType(); var document = Build(entity, GetAttributesToSerialize(entity), GetRelationshipsToSerialize(entity)); _currentTargetedResource = null; return(SerializeObject(document, _jsonSerializerSettings)); }
private IIdentifiable MakeProxy(IIdentifiable source) { var proxy = IdentifiableProxyBuilder.CreateProxy(source.GetType(), Repository); Copy(source, proxy); return proxy; }