2

Closed

Cannot DeepCopy objects containing IList<>

description

I have a pretty complex object structure that needs deep copying, and your project seemed like the obvious way to go. Among other things it contains several ILists, which creates a problem. To demonstrate it modify one of the tests to be the following:
        [TestMethod]
        public void ListOfClassCloneTest_ReferenceEqualityReturnsFalse()
        {
            IList<SimpleClass> source = Enumerable.Range(1, 10).Select(x => new SimpleClass() { _field = x, Property = x }).ToList();
            var target = CloneExtensions.CloneFactory.GetClone(source);
            Assert.AreNotSame(source, target);
            Assert.IsTrue(source.SequenceEqual(target));
            Assert.IsFalse(source.Zip(target, (s, t) => new { s, t }).Any(x => object.ReferenceEquals(x.s, x.t)));
        }
The following exception occurs:

Test method CloneExtensions.UnitTests.CollectionTests.ListOfClassCloneTest_ReferenceEqualityReturnsFalse threw exception: 
System.TypeInitializationException: The type initializer for 'CloneExtensions.CloneManager`1' threw an exception. ---> System.InvalidOperationException: No method 'GetEnumerator' exists on type 'System.Collections.Generic.IList`1[CloneExtensions.UnitTests.EntityClasses.SimpleClass]'.
    at System.Linq.Expressions.Expression.FindMethod(Type type, String methodName, Type[] typeArgs, Expression[] args, BindingFlags flags)
   at System.Linq.Expressions.Expression.Call(Expression instance, String methodName, Type[] typeArguments, Expression[] arguments)
   at CloneExtensions.ExpressionFactory`1.GetForeachAddExpression(Type collectionType) in ExpressionFactory.cs: line 192
   at CloneExtensions.ExpressionFactory`1.Initialize() in ExpressionFactory.cs: line 101
   at CloneExtensions.ExpressionFactory`1..ctor() in ExpressionFactory.cs: line 27
   at CloneExtensions.CloneManager`1..cctor() in CloneManager.cs: line 14
 --- End of inner exception stack trace ---
    at CloneExtensions.CloneManager`1.Clone(T source, CloningFlags flags, IDictionary`2 initializers) in CloneManager.cs: line 24
   at CloneExtensions.CloneFactory.GetClone(T source, CloningFlags flags, IDictionary`2 initializers) in CloneFactory.cs: line 52
   at CloneExtensions.CloneFactory.GetClone(T source, CloningFlags flags) in CloneFactory.cs: line 39
   at CloneExtensions.CloneFactory.GetClone(T source) in CloneFactory.cs: line 34
   at CloneExtensions.UnitTests.CollectionTests.ListOfClassCloneTest_ReferenceEqualityReturnsFalse() in CollectionTests.cs: line 35
Can this somehow be fixed, or is it a limitation of the .Net framework?

Thank you in advance.
Closed Mar 6, 2014 at 3:46 PM by marcinjuraszek

comments

marcinjuraszek wrote Mar 4, 2014 at 4:39 PM

Sounds like a bug. It's definitely possible to clone IList instance. I'll try to take care of this later today.

Nemo1024 wrote Mar 6, 2014 at 1:44 PM

Hi,
Did you manage to make any headway on this issue? It would be really appreciated if your library could work with IList generic.

wrote Mar 6, 2014 at 3:44 PM

wrote Mar 6, 2014 at 3:46 PM

Resolved with changeset 27780: IList collection item copy fix.

marcinjuraszek wrote Mar 6, 2014 at 3:50 PM

I've checked in fix for that. But even with the fix, to make it work you have to specify initialization expression for IList<>, because interface instance cannot be initialized without concrete type which implements that interface, and I don't want to make a decision what's the right type to initialize IList<> as.

Check IListOfClassCloneTest_ReferenceEqualityReturnsFalse test here: https://cloneextensions.codeplex.com/SourceControl/latest#CloneExtensions/CloneExtensions.UnitTests/CollectionTests.cs

Let me know if you have any questions or other feedback about library :)

-Marcin