public void TestSeparateDelegateIsCreatedForNestedOuter() { var ilCloner = new IlCloner(); var obj = new TestCollectionItem { Contents = new TestCollection { new TestCollectionItem { Text = "ZZZ" }, new TestCollectionItem { Text = "XXX" }, new TestCollectionItem { Text = "YYY" }, }, Text = "ZZZZ" }; var cloner = ilCloner.CreateClonerDelegate(obj); /* * IL_0000: ldarg.1 * IL_0001: stloc.0 * IL_0002: ldarg.0 * IL_0003: call Int32 get_Count()/System.Collections.CollectionBase * IL_0008: stloc.1 * IL_0009: ldc.i4.0 * IL_000a: stloc.2 * IL_000b: br.s IL_0025 * IL_000d: ldloc.0 * IL_000e: ldarg.0 * IL_000f: ldloc.2 * IL_0010: callvirt System.Object get_Item(Int32)/System.Collections.IList * IL_0015: ldnull * -- Here is the problem, one extra argument * -- The cached method was the outer one. * IL_0016: call TestCollectionItem DeepClone_TestCollectionItem(TestCollectionItem)/DynGen0000_CloneState_TestCollectionItem * IL_001b: callvirt Int32 Add(System.Object)/System.Collections.IList * IL_0020: pop * IL_0021: ldloc.2 * IL_0022: ldc.i4.1 * IL_0023: add * IL_0024: stloc.2 * IL_0025: ldloc.2 * IL_0026: ldloc.1 * IL_0027: blt.s IL_000d * IL_0029: ret */ try { cloner(obj); } catch (Exception e) { var k = e + ""; var j = 0; } }
public void TestSameNonGenericTypesClonedDifferently() { var ilCloner = new IlCloner(); var example = new TestTwoNonGenericMembersSameType() { ListA = new TestNonGenericList { "a", "b", "c", "d" }, ListB = new TestNonGenericList { 1, 2, 3, 4 } }; var cloner = ilCloner.CreateClonerDelegate(example); var exampleCloned = cloner(example); Assert.IsFalse(Object.ReferenceEquals(example, exampleCloned)); Assert.IsFalse(Object.ReferenceEquals(example.ListA, exampleCloned.ListA)); Assert.IsFalse(Object.ReferenceEquals(example.ListB, exampleCloned.ListB)); Assert.IsTrue(example.ListA.Cast <string>().SequenceEqual(exampleCloned.ListA.Cast <string>())); Assert.IsTrue(example.ListB.Cast <int>().SequenceEqual(exampleCloned.ListB.Cast <int>())); }
public void ClassAndStructCloning() { try { var ilCloner = new IlCloner(); var rootAsReferenceType = ExampleClass.GenerateExampleObject(); var rootAsValueType = ExampleClass.GenerateExampleObject().nestedStruct; var clonerRef = ilCloner.CreateClonerDelegate <ExampleClass>(); var clonerValue = ilCloner.CreateClonerDelegate <ExampleStruct>(); var clonedReference = clonerRef(rootAsReferenceType); var clonedStruct = clonerValue(rootAsValueType); Assert.IsTrue(rootAsReferenceType.Equals(clonedReference)); Assert.IsTrue(rootAsValueType.Equals(clonedStruct)); Assert.IsTrue(rootAsReferenceType.Equals(rootAsReferenceType.Clone())); } catch (Exception e) { var j = e + ""; throw; } }
public void TestArrayCloning() { var ilCloner = new IlCloner(); var exampleArray = new[] { Enumerable.Range(0, 10) .Select(i => ExampleClass.GenerateExampleObject()) .ToArray() } .ToArray(); var cloner = IlCloner.CreateCloner(exampleArray); var cloned = cloner(exampleArray); Assert.IsFalse(Object.ReferenceEquals(exampleArray, cloned)); for (var i = 0; i < exampleArray.Length; i++) { Assert.IsFalse(Object.ReferenceEquals(exampleArray[i], cloned[i])); for (var j = 0; j < exampleArray[i].Length; j++) { Assert.IsFalse(Object.ReferenceEquals(exampleArray[i][j], cloned[i][j])); Assert.IsTrue(exampleArray[i][j].Equals(cloned[i][j])); } } }
public void TestExplicitStraightCopy() { var obj = new TestClassWithStraightCopiedProp { Prop = new TestClassWithPropertyExclusion { PropA = "ASDF" } }; var cloner = IlCloner.Fluent(obj) .AlwaysStraightCopy(x => x.Prop) .CreateCloner(); var clonerDeep = Cloner.CreateClonerDelegate(obj); var cloned = cloner(obj); Assert.IsFalse(Object.ReferenceEquals(obj, cloned)); Assert.IsTrue(Object.ReferenceEquals(obj.Prop, cloned.Prop)); var clonedDeep = clonerDeep(obj); Assert.IsFalse(Object.ReferenceEquals(obj, clonedDeep)); Assert.IsFalse(Object.ReferenceEquals(obj.Prop, clonedDeep.Prop)); Assert.AreEqual(obj.Prop.PropA, clonedDeep.Prop.PropA); }
public void TestInitializedMembersNotDoublyInitialized() { var exampleObj = new TestClassWithInitializedMembers(); var countAtStart = TestClassWithConstructCount.Counter; var cloner = new IlCloner().CreateClonerDelegate(exampleObj); cloner(exampleObj); Assert.AreEqual(2, TestClassWithConstructCount.Counter - countAtStart); }
public void TestTypeWithCustomConstructor() { var ilCloner = new IlCloner(); ilCloner.DefineCustomConstructor <TestClassWithoutCtor>(c => TestClassWithoutCtor.Create()); var obj = TestClassWithoutCtor.Create(); obj.PropA = "JJJ"; ilCloner.CreateClonerDelegate <TestClassWithoutCtor>()(obj); }
public void TestDecimalType() { var cloner = new IlCloner(); var obj = new TestClassWithDecimal(); var del = cloner.CreateClonerDelegate(obj); var cloned = del(obj); Assert.IsFalse(Object.ReferenceEquals(obj, cloned)); Assert.AreEqual(obj.DecimalField, cloned.DecimalField); Assert.AreEqual(obj.DecimalProp, cloned.DecimalProp); }
public void TestIndexerBeingUsedForIListGeneric() { var ilCloner = new IlCloner(); var list = new TestList <int>(); for (var i = 0; i < 4; i++) { list.Add(i); } var cloner = IlCloner.CreateCloner(list); var newList = cloner(list); Assert.IsTrue(list.GetIndexerHit, "Get indexer was not accessed while cloning list"); }
public void TestStructCloning() { var obj = new TestStructOnly { PropA = "ASDF", PropB = 1234 }; var cloner = new IlCloner(); var del = cloner.CreateClonerDelegate(obj); var output = del(obj); Assert.AreEqual(obj.PropA, output.PropA); Assert.AreEqual(obj.PropB, output.PropB); }
public void TestStructWithClassCloning() { var obj = new TestNestedStruct_IS_CLASS { StructProp = new TestNestedClass_IS_STRUCT { ClassProp = new TestNestedStruct_IS_CLASS { StructProp = new TestNestedClass_IS_STRUCT() } } }; var cloner = new IlCloner(); var clonerStruct = cloner.CreateClonerDelegate(obj.StructProp); var clonedStruct = clonerStruct(obj.StructProp); }
public void TestClassWithStructCloning() { var obj = new TestNestedStruct_IS_CLASS { StructProp = new TestNestedClass_IS_STRUCT { ClassProp = new TestNestedStruct_IS_CLASS { StructProp = new TestNestedClass_IS_STRUCT() } } }; var cloner = new IlCloner(); var clonerClass = cloner.CreateClonerDelegate(obj); var clonedClass = clonerClass(obj); }
public void TestAbstractMember() { var cloner = new IlCloner(); var instance = new TestClassWIthAbstractMember { PropAbstract = new TestClassImplementingAbstract { PropA = "ASDF" } }; var del = cloner.CreateClonerDelegate(instance); var output = del(instance); Assert.IsFalse(Object.ReferenceEquals(instance, output)); Assert.IsFalse(Object.ReferenceEquals(instance.PropAbstract, output.PropAbstract)); Assert.AreEqual(instance.PropAbstract.GetType(), output.PropAbstract.GetType()); Assert.AreEqual(instance.PropAbstract.PropA, output.PropAbstract.PropA); }
public void TestInterfaceMember() { var cloner = new IlCloner(); var instance = new TestClassWithInterfaceMember { PropInterface = new TestClassImplementingInterface { PropA = "ASDF" } }; var del = cloner.CreateClonerDelegate(instance); var output = del(instance); Assert.IsFalse(Object.ReferenceEquals(instance, output)); Assert.IsFalse(Object.ReferenceEquals(instance.PropInterface, output.PropInterface)); Assert.AreEqual(instance.PropInterface.GetType(), output.PropInterface.GetType()); Assert.AreEqual(instance.PropInterface.PropA, output.PropInterface.PropA); }
public void TestNestedStructCloning() { var obj = new TestStructWithNestedStruct { Nested = new TestStructOnly { PropA = "ASDF", PropB = 1234 }, PropC = "ZZZZ" }; var cloner = new IlCloner(); var del = cloner.CreateClonerDelegate(obj); var output = del(obj); Assert.AreEqual(obj.Nested.PropA, output.Nested.PropA); Assert.AreEqual(obj.Nested.PropB, output.Nested.PropB); Assert.AreEqual(obj.PropC, output.PropC); }
public void TestNonGenericListContainingNonGenericListOfSameType() { var ilCloner = new IlCloner(); var example = new TestTwoNonGenericMembersSameType() { ListC = new TestNonGenericList() }; example.ListC.Add(new TestNonGenericList { 1, 2, 3, 4 }); var cloner = IlCloner.CreateCloner(example); var exampleCloned = cloner(example); Assert.IsFalse(Object.ReferenceEquals(example.ListC, exampleCloned.ListC)); Assert.IsFalse(Object.ReferenceEquals(example.ListC[0], exampleCloned.ListC[0])); }
public void TestThreadSafety() { var ilCloner = new IlCloner(); var threadCount = Math.Max(4, Environment.ProcessorCount - 1); var threadsRunning = 0; var start = false; var tasks = Enumerable.Range(0, threadCount) .Select(x => Task.Run(() => { Interlocked.Increment(ref threadsRunning); SpinWait.SpinUntil(() => start); ilCloner.CreateClonerDelegate <ExampleClass>(); })) .ToArray(); SpinWait.SpinUntil(() => threadsRunning == threadCount); start = true; Task.WaitAll(tasks); }
public void TestNonGenericListCloning() { var ilCloner = new IlCloner(); var example = new AsList { "A", "B", "C" }; var cloner = ilCloner.CreateClonerDelegate <AsList>(); var cloned = cloner(example); Assert.IsFalse(Object.ReferenceEquals(example, cloned)); Assert.IsTrue(example.SequenceEqual(cloned)); var nonGenList = new ExampleOldSchoolList(); ((IList)nonGenList).Add(example); ((IList)nonGenList).Add(example); ((IList)nonGenList).Add(example); ((IList)nonGenList).Add(example); ((IList)nonGenList).Add(example); ((IList)nonGenList).Add(example); var clonerNonGen = IlCloner.CreateCloner(nonGenList); var clonedNonGen = clonerNonGen(nonGenList); Assert.IsFalse(Object.ReferenceEquals(nonGenList, clonedNonGen)); Assert.IsTrue(example.SequenceEqual(cloned)); for (var i = 0; i < nonGenList.Count; i++) { Assert.IsFalse(Object.ReferenceEquals(((IList)nonGenList)[i], ((IList)clonedNonGen)[i])); } }
public IlClonerFluent() { _cloner = new IlCloner(); }
public IlClonerFluent(IlCloner cloner) { _cloner = cloner; }
public static Action Benchmark <T>(T obj, int countToRun = 1000000, bool cloneProps = true) where T : class, ICloneable { var message = ""; var timer = new Stopwatch(); timer.Start(); IlCloner.Default.ShouldCloneProperties = cloneProps; IlCloner.Default.UseExistingCloners = false; var example = obj; var cloneGenStart = timer.Elapsed; var cloner = IlCloner.CreateCloner <T>(); message += $"{(timer.Elapsed - cloneGenStart).TotalMilliseconds.ToString("n2")}ms to generate cloner." + Environment.NewLine; // Dry run cloner(example); example.Clone(); var actions = new[] { new { Name = "IL Generated", Action = new Action(() => cloner(example)) }, new { Name = "C# Clone() method", Action = new Action(() => example.Clone()) } }; Action iteration = () => { var deferred = new List <Action>(); var maxClonesSec = 0.0; double?minClonesSec = null; var messages = actions.ToDictionary(a => a.Name, a => new List <string>()); string fastest = null; foreach (var a in actions) { GC.Collect(); System.Threading.Thread.Sleep(1000); var startTime = timer.Elapsed; for (var i = 0; i < countToRun; i++) { a.Action(); } var totalTime = timer.Elapsed - startTime; var clonesSec = (countToRun / totalTime.TotalSeconds); maxClonesSec = Math.Max(maxClonesSec, clonesSec); if (minClonesSec.HasValue) { minClonesSec = Math.Min(minClonesSec.Value, clonesSec); } else { minClonesSec = clonesSec; } deferred.Add( () => { messages[a.Name].Add($"{clonesSec.ToString("n2")} clones per second."); if (clonesSec != maxClonesSec) { var frac = (clonesSec / maxClonesSec); messages[a.Name].Add($"{(100.0 - frac * 100.0).ToString("0.00")}% ({frac.ToString("0.00")} times) slower than best performer."); } if (clonesSec != minClonesSec.Value) { var frac = (clonesSec / minClonesSec).Value; messages[a.Name].Add($"{(frac * 100.0 - 100.0).ToString("0.00")}% ({frac.ToString("0.00")} times) faster than worst performer."); } if (clonesSec == maxClonesSec) { fastest = a.Name; } } ); } deferred.ForEach(d => d()); var nameFieldLength = actions.Max(a => a.Name.Length) + 4; message += string.Join( Environment.NewLine + Environment.NewLine, actions .Select(a => { return(string.Join( Environment.NewLine, messages[a.Name].Select((m, idx) => { if (idx == 0) { return $"{a.Name}:".PadRight(nameFieldLength) + m; } else if (idx == 1 && a.Name == fastest) { return "".PadRight(a.Name.Length, '^').PadRight(nameFieldLength) + m; } else { return "".PadRight(nameFieldLength) + m; } }) )); }) ); Console.WriteLine(message); Console.ReadLine(); message = ""; }; iteration(); return(iteration); }
public void TestTypeWithoutConstructor() { var ilCloner = new IlCloner(); ilCloner.CreateClonerDelegate <TestClassWithoutCtor>(); }