// The logic is similar to UpdateCloneReferences. // the difference is in this function, we need to set reference by Property. void UpdateCloneReferenceByModelItem (FlowNode currentFlowElement, Dictionary<FlowNode, ModelItem> modelItems, Dictionary<FlowNode, FlowNode> clonedFlowElements) { if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType())) { FlowStep currentFlowStep = (FlowStep)currentFlowElement; FlowStep clonedFlowStep = (FlowStep)clonedFlowElements[currentFlowElement]; ModelItem modelItem = modelItems[clonedFlowStep]; FlowNode nextFlowElement = currentFlowStep.Next; if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement)) { modelItem.Properties["Next"].SetValue(clonedFlowElements[nextFlowElement]); } else { modelItem.Properties["Next"].SetValue(null); } } else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType())) { if (!modelItems.ContainsKey(currentFlowElement)) { Fx.Assert("Should not happen."); } FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement; FlowDecision clonedFlowDecision = (FlowDecision)clonedFlowElements[currentFlowElement]; Fx.Assert(currentFlowDecision == clonedFlowDecision, "should not happen"); ModelItem modelItem = modelItems[currentFlowElement]; Fx.Assert(modelItem != null, "should not happen"); FlowNode trueElement = currentFlowDecision.True; FlowNode falseElement = currentFlowDecision.False; if (trueElement != null && clonedFlowElements.ContainsKey(trueElement)) { modelItem.Properties["True"].SetValue(clonedFlowElements[trueElement]); } else { modelItem.Properties["True"].SetValue(null); } if (falseElement != null && clonedFlowElements.ContainsKey(falseElement)) { modelItem.Properties["False"].SetValue(clonedFlowElements[falseElement]); } else { modelItem.Properties["False"].SetValue(null); } } else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType())) { GenericFlowSwitchHelper.ReferenceCopy(currentFlowElement.GetType().GetGenericArguments()[0], currentFlowElement, modelItems, clonedFlowElements); } else { Debug.Fail("Unknown FlowNode"); } }
//This does a shallow copy of all the public properties with getter and setter. //It also replicates Xaml Attached properties. FlowNode CloneFlowElement(FlowNode flowElement, Predicate<AttachableMemberIdentifier> allowAttachableProperty = null) { Type flowElementType = flowElement.GetType(); FlowNode clonedObject = (FlowNode)Activator.CreateInstance(flowElementType); foreach (PropertyInfo propertyInfo in flowElementType.GetProperties()) { if (propertyInfo.GetGetMethod() != null && propertyInfo.GetSetMethod() != null) { propertyInfo.SetValue(clonedObject, propertyInfo.GetValue(flowElement, null), null); } } //Replicate any Xaml Attached Property. KeyValuePair<AttachableMemberIdentifier, object>[] attachedProperties = new KeyValuePair<AttachableMemberIdentifier, object>[AttachablePropertyServices.GetAttachedPropertyCount(flowElement)]; AttachablePropertyServices.CopyPropertiesTo(flowElement, attachedProperties, 0); foreach (KeyValuePair<AttachableMemberIdentifier, object> attachedProperty in attachedProperties) { if (allowAttachableProperty != null && !allowAttachableProperty(attachedProperty.Key)) { continue; } AttachablePropertyServices.SetProperty(clonedObject, attachedProperty.Key, attachedProperty.Value); } return clonedObject; }
//This method updates the clone of currentFlowElement to reference cloned FlowElements. void UpdateCloneReferences(FlowNode currentFlowElement, Dictionary<FlowNode, FlowNode> clonedFlowElements) { if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType())) { FlowStep currentFlowStep = (FlowStep)currentFlowElement; FlowStep clonedFlowStep = (FlowStep)clonedFlowElements[currentFlowElement]; FlowNode nextFlowElement = currentFlowStep.Next; if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement)) { clonedFlowStep.Next = clonedFlowElements[nextFlowElement]; } else { clonedFlowStep.Next = null; } } else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType())) { FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement; FlowDecision clonedFlowDecision = (FlowDecision)clonedFlowElements[currentFlowElement]; FlowNode trueElement = currentFlowDecision.True; FlowNode falseElement = currentFlowDecision.False; if (trueElement != null && clonedFlowElements.ContainsKey(trueElement)) { clonedFlowDecision.True = clonedFlowElements[trueElement]; } else { clonedFlowDecision.True = null; } if (falseElement != null && clonedFlowElements.ContainsKey(falseElement)) { clonedFlowDecision.False = clonedFlowElements[falseElement]; } else { clonedFlowDecision.False = null; } } else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType())) { GenericFlowSwitchHelper.Copy(currentFlowElement.GetType().GetGenericArguments()[0], currentFlowElement, clonedFlowElements); } else { Debug.Fail("Unknown FlowNode"); } }