/// <summary> /// Clones all writable properties, importantly handling strings and primitives /// </summary> /// <param name="target"></param> /// <returns><see cref="target"/>, as a convenience</returns> protected virtual DictionaryNodeOptions DeepCloneInto(DictionaryNodeOptions target) { var properties = GetType().GetProperties(); foreach (var property in properties.Where(prop => prop.CanWrite)) // Skip any read-only properties { var originalValue = property.GetValue(this, null); property.SetValue(target, originalValue, null); } return(target); }
protected override DictionaryNodeOptions DeepCloneInto(DictionaryNodeOptions target) { base.DeepCloneInto(target); ((DictionaryNodeWritingSystemOptions)target).Options = Options.Select(dno => new DictionaryNodeListOptions.DictionaryNodeOption { Id = dno.Id, IsEnabled = dno.IsEnabled }).ToList(); return(target); }
/// <summary> /// Clone this node, point to the given Parent. Deep-clone Children and DictionaryNodeOptions /// </summary> /// <remarks> /// Grouping node children are cloned only if this is a recursive call. /// Referenced children are cloned only if this is NOT a recursive call. /// </remarks> internal ConfigurableDictionaryNode DeepCloneUnderParent(ConfigurableDictionaryNode parent, bool isRecursiveCall = false) { var clone = new ConfigurableDictionaryNode(); // Copy everything over at first, importantly handling strings, bools. var properties = typeof(ConfigurableDictionaryNode).GetProperties(); foreach (var property in properties) { // Skip Parent and read-only properties (eg DisplayLabel) if (!property.CanWrite || property.Name == "Parent") { continue; } var originalValue = property.GetValue(this, null); property.SetValue(clone, originalValue, null); } clone.ReferencedNode = ReferencedNode; // GetProperties() doesn't return internal properties; copy here clone.Parent = parent; // Deep-clone Children if (Children != null && Children.Any()) { if (isRecursiveCall || !(DictionaryNodeOptions is DictionaryNodeGroupingOptions)) { // Cloned children should point to their newly-cloned parent clone.Children = Children.Select(child => child.DeepCloneUnderParent(clone, true)).ToList(); } else { // Cloning children of a group creates problems because the children can be moved out of the group. // Also the only expected use of cloning a group is to get a new group to group different children. clone.Children = null; } } else if (!isRecursiveCall && ReferencedNode != null && ReferencedNode.Children != null) { // Allow users to configure copies of Shared nodes (e.g. Subentries) separately clone.ReferencedNode = null; clone.ReferenceItem = null; clone.Children = ReferencedNode.Children.Select(child => child.DeepCloneUnderParent(clone, true)).ToList(); } // Deep-clone DictionaryNodeOptions if (DictionaryNodeOptions != null) { clone.DictionaryNodeOptions = DictionaryNodeOptions.DeepClone(); } return(clone); }