示例#1
0
        private CompositeDefinitionProcessorContext CreateChildProcessorContext(TBuildResult parentResult,
                                                                                CompositeDefinitionProcessorContext processorContext,
                                                                                TBuilderContext parentingBuilderContext,
                                                                                XElement childElement,
                                                                                ResourceClassBase currentResourceClass,
                                                                                IResourceModel resourceModel, int childIndex)
        {
            ResourceClassBase  childModel;
            AssociationView    association;
            ResourceMemberBase resourceMember;

            string childMemberName        = childElement.AttributeValue(CompositeDefinitionHelper.Name);
            string childMemberDisplayName = childElement.AttributeValue(CompositeDefinitionHelper.DisplayName);
            string currentElementName     = processorContext.CurrentElement.AttributeValue(CompositeDefinitionHelper.Name);

            string resourceMemberName    = string.Empty;
            string childEntityMemberName = string.Empty;

            switch (childElement.Name.LocalName)
            {
            case CompositeDefinitionHelper.Collection:

                if (!currentResourceClass.CollectionByName.TryGetValue(childMemberName, out Collection collection))
                {
                    ApplyValidationMessage("collection", childMemberName, currentElementName);
                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is a collection named '{childMemberName}'.");

                childModel            = collection.ItemType;
                childEntityMemberName = childMemberName;
                association           = collection.Association;
                resourceMember        = collection;
                resourceMemberName    = collection.PropertyName;

                break;

            case CompositeDefinitionHelper.LinkedCollection:

                var resource = currentResourceClass as Resource;

                if (resource == null)
                {
                    _logger.Debug($"Current resource class '{currentResourceClass.Name} is not an aggregate root.");
                    return(null);
                }

                if (!resource.LinkedResourceCollectionByName.TryGetValue(childMemberName, out LinkedCollection linkedCollection))
                {
                    ApplyValidationMessage("linked collection", childMemberName, currentElementName);
                    return(null);
                }

                _logger.Debug(
                    $"Current element '{currentElementName} is a linked collection named '{childMemberName}' for resource '{currentResourceClass.Name}'.");

                childModel            = linkedCollection.Resource;
                childEntityMemberName = childMemberName;
                association           = linkedCollection.Association;
                resourceMember        = linkedCollection;
                resourceMemberName    = linkedCollection.PropertyName;

                break;

            case CompositeDefinitionHelper.EmbeddedObject:

                if (!currentResourceClass.EmbeddedObjectByName.TryGetValue(childMemberName, out EmbeddedObject embeddedObject))
                {
                    ApplyValidationMessage("embedded object", childMemberName, currentElementName);

                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is an embedded object named '{childMemberName}'.");

                childModel            = embeddedObject.ObjectType;
                childEntityMemberName = embeddedObject.Association.Name;
                association           = embeddedObject.Association;
                resourceMember        = embeddedObject;
                resourceMemberName    = embeddedObject.PropertyName;

                if (CompositeDefinitionHelper.ShouldFlatten(childElement))
                {
                    _logger.Debug($"Flattening embedded object {childModel.Name}");

                    _compositeBuilder.ApplyFlattenedMember(embeddedObject, parentingBuilderContext);

                    var childBuilderContextForObject = _compositeBuilder.CreateFlattenedReferenceChildContext(parentingBuilderContext);

                    var childProcessorContextForObject = new CompositeDefinitionProcessorContext(
                        processorContext.CompositeDefinitionElement,
                        resourceModel,
                        childElement,
                        childModel,
                        association,
                        childEntityMemberName,
                        resourceMemberName,
                        childIndex,
                        resourceMember);

                    ProcessChildren(parentResult, childProcessorContextForObject, childBuilderContextForObject);

                    return(null);
                }

                break;

            case CompositeDefinitionHelper.ReferencedResource:

                if (!currentResourceClass.ReferenceByName.TryGetValue(childMemberName, out Reference reference))
                {
                    ApplyValidationMessage("referenced resource", childMemberName, currentElementName);

                    return(null);
                }

                _logger.Debug($"Current element '{currentElementName}' is an referenced resourced named '{childMemberName}'.");

                childModel            = reference.ReferencedResource;
                childEntityMemberName = reference.Association.Name;
                association           = reference.Association;
                resourceMember        = reference;
                resourceMemberName    = reference.PropertyName;

                // If reference is flattened, process recursively without adding another query at this level.
                if (CompositeDefinitionHelper.ShouldFlatten(childElement))
                {
                    _logger.Debug($"Flattening referenced resource {childModel.Name}");

                    _compositeBuilder.ApplyFlattenedMember(reference, parentingBuilderContext);

                    var childBuilderContextForReference = _compositeBuilder.CreateFlattenedReferenceChildContext(parentingBuilderContext);

                    var childProcessorContextForReference = new CompositeDefinitionProcessorContext(
                        processorContext.CompositeDefinitionElement,
                        resourceModel,
                        childElement,
                        childModel,
                        association,
                        childEntityMemberName,
                        resourceMemberName,
                        childIndex,
                        resourceMember);

                    if (childModel.Entity.IsAggregateRoot)
                    {
                        // Provide opportunity to perform processing related to navigating into another resource (i.e. authorization)
                        if (!_compositeBuilder.TryIncludeResource(childProcessorContextForReference, childBuilderContextForReference))
                        {
                            return(null);
                        }
                    }

                    ProcessChildren(parentResult, childProcessorContextForReference, childBuilderContextForReference);

                    return(null);
                }

                break;

            default:

                throw new NotSupportedException($"Element '{childElement.Name.LocalName}' is not supported.");
            }

            return(new CompositeDefinitionProcessorContext(
                       processorContext.CompositeDefinitionElement,
                       resourceModel,
                       childElement,
                       childModel,
                       association,
                       childEntityMemberName,
                       childMemberDisplayName ?? resourceMemberName,
                       childIndex,
                       resourceMember));
        }