private void Initialize() { foreach (var typeId in typesService.GetRegisteredTypes()) { if (!typesService.IsScalarType(typeId)) { var type = typesService.GetTypeFromId(typeId); var rule = new TypeMergeRule(); Type collectionType = null; Type dictionaryType = null; if (!Utils.IsCollectionType(type, ref collectionType) && !Utils.IsDictionaryType(type, ref dictionaryType)) { var attributes = type.GetCustomAttributes(typeof(ConcurrentAttribute), true); if (attributes.Length == 1) { rule.IsConcurrent = true; rule.IsStaticConcurrency = ((ConcurrentAttribute)attributes[0]).Behavior == ConcurrentBehavior.Static; if (!rule.IsStaticConcurrency) { rule.DynamicResolverType = ((ConcurrentAttribute)attributes[0]).Resolver; } else { foreach (var edge in typesService.GetTypeEdges(typeId)) { if (edge.Data.Semantic == Graph.EdgeType.Property) { var memberId = edge.ToNodeId; //var memberTypeId = typesService.GetMemberTypeId(memberId); var memberName = typesService.GetMemberName(typeId, memberId); PropertyInfo propertyInfo = FindPropertyInfo(type, memberName); bool isOverride = propertyInfo.GetCustomAttributes(typeof(OverrideAttribute), false).Length == 1; rule.IsMemberOverride.Add(memberId, isOverride); } } } } } else { rule.IsConcurrent = true; rule.IsStaticConcurrency = true; } // Add rule for the type in cache typeMergeRules.Add(typeId, rule); } } }
private static void LogObject(Guid nodeId, Node <Guid, object, EdgeData> node, INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { var typeId = typesService.GetInstanceTypeId(node); var typeName = typesService.GetTypeFromId(typeId).Name; Debug.WriteLine(LogTabs(tabLevel) + nodeId + "(" + typeName + ")"); Debug.WriteLine(LogTabs(tabLevel) + "Previous=" + node.Previous); foreach (var value in node.Values) { Debug.WriteLine(LogTabs(tabLevel) + typesService.GetMemberName(typeId, value.Key) + "=" + value.Value); } foreach (var edge in node.Edges) { if (edge.Value.Data.Semantic == EdgeType.Property) { Debug.WriteLine(LogTabs(tabLevel) + typesService.GetMemberName(typeId, (Guid)edge.Value.Data.Data) + "="); LogNodesRecursive(edge.Value.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } } }
private void MergeObjectsStatic(Guid nodeId, Guid typeId, Node <Guid, object, EdgeData> originalNode, Node <Guid, object, EdgeData> changedNode, Node <Guid, object, EdgeData> node, MergeRecursiveDelegate mergeRecursive, InsertRecursiveDelegate insertRecursive, RecursiveResolutionParameters parameters) { // Consolidate the values foreach (var item in originalNode.Values) { // Value was changed compared to previous version if (!changedNode.Values[item.Key].Equals(item.Value)) { // Try setting value in the node, if it is still the same if (node.Values[item.Key].Equals(item.Value)) { node.Values[item.Key] = changedNode.Values[item.Key]; } else { if (objectAttributeProvider.IsMemberOverride(typeId, item.Key)) { // Override with changed value node.Values[item.Key] = changedNode.Values[item.Key]; } else { throw new ConcurrentModificationException("Concurrent modification of scalar value not allowed in type:" + typesService.GetTypeFromId(typeId).ToString() + " for member " + typesService.GetMemberName(typeId, item.Key)); } } } } // Consolidate the edges foreach (var edge in originalNode.Edges) { // Value was changed compared to previous version if (!changedNode.Edges[edge.Key].ToNodeId.Equals(edge.Value.ToNodeId)) { // Was member set to override? bool isOverride = objectAttributeProvider.IsMemberOverride(typeId, (Guid)edge.Key.Data); // Try setting value in the node, if it is still the same or if override is set if (node.Edges[edge.Key].ToNodeId.Equals(edge.Value.ToNodeId) || isOverride) { Guid newReference = changedNode.Edges[edge.Key].ToNodeId; Guid newReferenceUpdated = Guid.Empty; // Is there an intermediate change? if (parameters.IntermediateChanges.TryGetValue(newReference, out newReferenceUpdated)) { // Set edge to node from the changed node node.SetEdgeToNode(edge.Value.Data, newReferenceUpdated); // See about the new object mergeRecursive(newReferenceUpdated, parameters); } else { NodeState nodeState = NodeState.None; parameters.ChangeSet.NodeStates.TryGetValue(newReference, out nodeState); // If changed node is a new node go into the changed node recursion if (nodeState == NodeState.Created) { // Set the new reference node.SetEdgeToNode(edge.Value.Data, newReference); // Insert the new nodes insertRecursive(newReference, parameters); } else { // Set the new reference node.SetEdgeToNode(edge.Value.Data, newReference); // Follow the new reference and see changes mergeRecursive(newReference, parameters); } } } else { throw new ConcurrentModificationException("Concurrent modification of referenced item not allowed in type:" + typesService.GetTypeFromId(typeId).ToString() + " for member " + typesService.GetMemberName(typeId, (Guid)edge.Key.Data)); } } else { mergeRecursive(node.Edges[edge.Key].ToNodeId, parameters); } } }