/// <summary> /// Parses all relationships from <paramref name="type" /> to other models in the resource resourceGraphs by constructing RelationshipProxies . /// </summary> /// <param name="type"> /// The type to parse /// </param> private void RegisterRelationshipProxies(RightType type) { foreach (RelationshipAttribute attr in _resourceGraph.GetRelationships(type)) { if (!attr.CanInclude) { continue; } if (!_relationshipProxies.TryGetValue(attr, out _)) { RightType rightType = GetRightTypeFromRelationship(attr); bool isContextRelation = false; ISet <RelationshipAttribute> relationshipsToUpdate = _targetedFields.Relationships; if (relationshipsToUpdate != null) { isContextRelation = relationshipsToUpdate.Contains(attr); } var proxy = new RelationshipProxy(attr, rightType, isContextRelation); _relationshipProxies[attr] = proxy; } } }
/// <summary> /// Create a next layer from any previous layer /// </summary> /// <returns> /// The next layer. /// </returns> /// <param name="nodes">Nodes.</param> public IEnumerable <IResourceNode> CreateNextLayer(IEnumerable <IResourceNode> nodes) { // first extract resources by parsing populated relationships in the resources // of previous layer (Dictionary <RelationshipProxy, List <IIdentifiable> > lefts, Dictionary <RelationshipProxy, List <IIdentifiable> > rights) = ExtractResources(nodes); // group them conveniently so we can make ChildNodes of them: // there might be several relationship attributes in rights dictionary // that point to the same right type. IDictionary <RightType, List <KeyValuePair <RelationshipProxy, List <IIdentifiable> > > > leftsGrouped = GroupByRightTypeOfRelationship(lefts); // convert the groups into child nodes List <IResourceNode> nextNodes = leftsGrouped.Select(entry => { RightType nextNodeType = entry.Key; RegisterRelationshipProxies(nextNodeType); var populatedRelationships = new List <RelationshipProxy>(); List <IRelationshipGroup> relationshipsToPreviousLayer = entry.Value.Select(grouped => { RelationshipProxy proxy = grouped.Key; populatedRelationships.AddRange(GetPopulatedRelationships(nextNodeType, rights[proxy])); return(CreateRelationshipGroupInstance(nextNodeType, proxy, grouped.Value, rights[proxy])); }).ToList(); return(CreateNodeInstance(nextNodeType, populatedRelationships.ToArray(), relationshipsToPreviousLayer)); }).ToList(); return(nextNodes); }
private void Reassign(IEnumerable <IIdentifiable> leftResources, RelationshipProxy proxy, HashSet <TResource> unique) { foreach (IIdentifiable left in leftResources) { var currentValue = proxy.GetValue(left); if (currentValue is IEnumerable <IIdentifiable> relationshipCollection) { var intersection = relationshipCollection.Intersect(unique, _comparer); IEnumerable typedCollection = TypeHelper.CopyToTypedCollection(intersection, relationshipCollection.GetType()); proxy.SetValue(left, typedCollection); } else if (currentValue is IIdentifiable relationshipSingle) { if (!unique.Intersect(new HashSet <IIdentifiable> { relationshipSingle }, _comparer).Any()) { proxy.SetValue(left, null); } } } }
/// <summary> /// Reflective helper method to create an instance of <see cref="RelationshipGroup{TRight}" />; /// </summary> private IRelationshipGroup CreateRelationshipGroupInstance(RightType thisLayerType, RelationshipProxy proxy, List <IIdentifiable> leftResources, List <IIdentifiable> rightResources) { IEnumerable rightResourceSet = CollectionConverter.CopyToHashSet(rightResources, thisLayerType); return((IRelationshipGroup)ObjectFactory.CreateInstanceOfOpenType(typeof(RelationshipGroup <>), thisLayerType, proxy, new HashSet <IIdentifiable>(leftResources), rightResourceSet)); }
private void AddToRelationshipGroup(Dictionary <RelationshipProxy, List <IIdentifiable> > target, RelationshipProxy proxy, IEnumerable <IIdentifiable> newResources) { if (!target.TryGetValue(proxy, out List <IIdentifiable> resources)) { resources = new List <IIdentifiable>(); target[proxy] = resources; } resources.AddRange(newResources); }
public RelationshipGroup(RelationshipProxy proxy, HashSet <IIdentifiable> leftResources, HashSet <TRight> rightResources) { Proxy = proxy; LeftResources = leftResources; RightResources = rightResources; }
/// <summary> /// Reflective helper method to create an instance of <see cref="RelationshipGroup{TRight}"/>; /// </summary> private IRelationshipGroup CreateRelationshipGroupInstance(Type thisLayerType, RelationshipProxy proxy, List <IIdentifiable> leftResources, List <IIdentifiable> rightResources) { var rightResourcesHashed = TypeHelper.CreateInstanceOfOpenType(typeof(HashSet <>), thisLayerType, TypeHelper.CopyToList(rightResources, thisLayerType)); return((IRelationshipGroup)TypeHelper.CreateInstanceOfOpenType(typeof(RelationshipGroup <>), thisLayerType, proxy, new HashSet <IIdentifiable>(leftResources), rightResourcesHashed)); }