Dictionary Cloner
DictionaryCloner<Dictionary, Key, Value> implements ICloner<Dictionary> cloner.
// Create cloner
ICloner<IDictionary<int, string>> cloner = new DictionaryCloner<int, string>().SetReadOnly();
// Create dictionary
IDictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
IDictionary<int, string> clone = cloner.Clone(dictionary);
DictionaryCloner.Create(dictionaryType) also creates dictionary same cloner.
// Create cloner
ICloner<Dictionary<int, string>> cloner =
(ICloner<Dictionary<int, string>>)
DictionaryCloner.Create(typeof(Dictionary<int, string>)).SetReadOnly();
DictionaryCloner<Interface, Key, Value, Implementation> implements ICloner<Interface> cloner.
// Create cloner
ICloner<IDictionary<int, string>> cloner =
new DictionaryCloner<IDictionary<int, string>, int, string, LockableDictionary<int, string>>()
.SetReadOnly();
// Create dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
IDictionary<int, string> clone = cloner.Clone(dictionary);
DictionaryCloner.Create(interfaceType, implementationType) also creates dictionary cloner.
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>), typeof(LockableDictionary<int, string>))
.SetReadOnly();
ThrowOnNull
.SetThrowOnNull(false) sets policy to pass null as is. This is default policy.
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>))
.SetThrowOnNull(false)
.SetReadOnly();
// Create clone (of null)
IDictionary<int, string>? clone = cloner.Clone(null!); // -> null
.SetThrowOnNull(true) sets policy to throw ArgumentNullException on null input value.
try
{
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>))
.SetThrowOnNull(true)
.SetReadOnly();
// Create clone (of null)
IDictionary<int, string>? clone = cloner.Clone(null!); // -> null
}
catch (ArgumentNullException)
{
}
Deep Cloner
.SetKeyCloner(keyCloner) and .SetValueCloner(valueCloner) assign cloners that clones each element. If assigned the clone is deep, otherwise shallow.
// Create record cloner
ICloner<MyRecord> recordCloner = (ICloner<MyRecord>)RecordCloner.Create(typeof(MyRecord));
// Create array cloner
ICloner<MyRecord[]> cloner =
(ICloner<MyRecord[]>)
ArrayCloner.Create(typeof(MyRecord))
.SetElementCloner(recordCloner)
.SetReadOnly();
// Create record
MyRecord myRecord = new MyRecord();
myRecord.IdMap[10] = 15;
// Create array
MyRecord[] array = new[] { myRecord };
// Create array clone
MyRecord[] clones = cloner.Clone(array);
// Assert not same reference
WriteLine(Object.ReferenceEquals(clones, array)); // False
WriteLine(Object.ReferenceEquals(clones[0], array[0])); // False
public record MyRecord
{
public IDictionary<int, int> IdMap = new Dictionary<int, int>();
}
Graph Cloner
Use .SetCyclical(true) to indicate cyclical graph clone.
// Create node cloner
ICloner<Node> nodeCloner = (ICloner<Node>)RecordCloner.Create(typeof(Node)).SetCyclical(true);
// Create array cloner
ICloner<Node[]> graphCloner =
(ICloner<Node[]>)
ArrayCloner.Create(typeof(Node))
.SetElementCloner(nodeCloner)
.SetCyclical(true)
.SetReadOnly();
// Create graph
Node node1 = new Node { Id = 1 };
Node node2 = new Node { Id = 2 };
Node node3 = new Node { Id = 3 };
node1.Edges[2] = node2;
node2.Edges[3] = node3;
node3.Edges[1] = node1;
Node[] graph = new[] { node1, node2, node3 };
// Clone
Node[] clone = graphCloner.Clone(graph);
// Assert not same reference
WriteLine(Object.ReferenceEquals(graph, clone)); // False
WriteLine(Object.ReferenceEquals(graph[0], clone[0])); // False
public class Node
{
public int Id;
public IDictionary<int, Node> Edges = new Dictionary<int, Node>();
}
⇒
Full Example
Full example
using System;
using System.Collections.Generic;
using System.Linq;
using Avalanche.Utilities;
using static System.Console;
public class dictionarycloner
{
public static void Run()
{
// Dictionary Cloner
{
// <11>
// Create cloner
ICloner<IDictionary<int, string>> cloner = new DictionaryCloner<int, string>().SetReadOnly();
// Create dictionary
IDictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
IDictionary<int, string> clone = cloner.Clone(dictionary);
// </11>
// Print clone
Print(clone);
}
{
// <12>
// Create cloner
ICloner<Dictionary<int, string>> cloner =
(ICloner<Dictionary<int, string>>)
DictionaryCloner.Create(typeof(Dictionary<int, string>)).SetReadOnly();
// </12>
// Create dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
Dictionary<int, string> clone = cloner.Clone(dictionary);
// Print clone
Print(clone);
}
{
// <13>
// Create cloner
ICloner<IDictionary<int, string>> cloner =
new DictionaryCloner<IDictionary<int, string>, int, string, LockableDictionary<int, string>>()
.SetReadOnly();
// Create dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
IDictionary<int, string> clone = cloner.Clone(dictionary);
// </13>
// Print clone
Print(clone);
}
{
// <14>
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>), typeof(LockableDictionary<int, string>))
.SetReadOnly();
// </14>
// Create dictionary
Dictionary<int, string> dictionary = new Dictionary<int, string> { { 1, "A" }, { 2, "B" }, { 3, "C" } };
// Create clone
IDictionary<int, string> clone = cloner.Clone(dictionary);
// Print clone
Print(clone);
}
// ThrowOnNull
{
// <31>
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>))
.SetThrowOnNull(false)
.SetReadOnly();
// Create clone (of null)
IDictionary<int, string>? clone = cloner.Clone(null!); // -> null
// </31>
}
{
// <32>
try
{
// Create cloner
ICloner<IDictionary<int, string>> cloner =
(ICloner<IDictionary<int, string>>)
DictionaryCloner.Create(typeof(IDictionary<int, string>))
.SetThrowOnNull(true)
.SetReadOnly();
// Create clone (of null)
IDictionary<int, string>? clone = cloner.Clone(null!); // -> null
}
catch (ArgumentNullException)
{
}
// </32>
}
// Deep Cloner
{
// <41>
// Create record cloner
ICloner<MyRecord> recordCloner = (ICloner<MyRecord>)RecordCloner.Create(typeof(MyRecord));
// Create array cloner
ICloner<MyRecord[]> cloner =
(ICloner<MyRecord[]>)
ArrayCloner.Create(typeof(MyRecord))
.SetElementCloner(recordCloner)
.SetReadOnly();
// Create record
MyRecord myRecord = new MyRecord();
myRecord.IdMap[10] = 15;
// Create array
MyRecord[] array = new[] { myRecord };
// Create array clone
MyRecord[] clones = cloner.Clone(array);
// Assert not same reference
WriteLine(Object.ReferenceEquals(clones, array)); // False
WriteLine(Object.ReferenceEquals(clones[0], array[0])); // False
// </41>
}
// Graph Cloner
{
// <51>
// Create node cloner
ICloner<Node> nodeCloner = (ICloner<Node>)RecordCloner.Create(typeof(Node)).SetCyclical(true);
// Create array cloner
ICloner<Node[]> graphCloner =
(ICloner<Node[]>)
ArrayCloner.Create(typeof(Node))
.SetElementCloner(nodeCloner)
.SetCyclical(true)
.SetReadOnly();
// Create graph
Node node1 = new Node { Id = 1 };
Node node2 = new Node { Id = 2 };
Node node3 = new Node { Id = 3 };
node1.Edges[2] = node2;
node2.Edges[3] = node3;
node3.Edges[1] = node1;
Node[] graph = new[] { node1, node2, node3 };
// Clone
Node[] clone = graphCloner.Clone(graph);
// Assert not same reference
WriteLine(Object.ReferenceEquals(graph, clone)); // False
WriteLine(Object.ReferenceEquals(graph[0], clone[0])); // False
// </51>
}
}
static void Print<T>(IEnumerable<T> enumr) => Console.WriteLine(String.Join(", ", enumr));
static void PrintArray<T>(IEnumerable<IEnumerable<T>> enumr) => Console.WriteLine($"[{String.Join("], [", enumr.Select(array => String.Join(", ", array)))}]");
// <98>
public record MyRecord
{
public IDictionary<int, int> IdMap = new Dictionary<int, int>();
}
// </98>
// <99>
public class Node
{
public int Id;
public IDictionary<int, Node> Edges = new Dictionary<int, Node>();
}
// </99>
}