AqlaSolutions / AqlaSerializer

Binary serializer with full .NET support!
http://www.aqla.net
Other
17 stars 3 forks source link

IList clone changes the type #26

Closed inethui closed 2 years ago

inethui commented 2 years ago

The following unit test fails on the second assert: Expected: typeof(int[]) Actual: typeof(System.Collections.Generic.List)

    [Fact]
    private void CloneListOfList()
    {
        var listOfList = new List<IList<int>> { new[] { 1, 2 } };
        var clone = Serializer.DeepClone(listOfList );
        Assert.Equal(listOfList .Count, clone.Count);
        Assert.Equal(listOfList [0].GetType(), clone[0].GetType());
    }

The problem is that the original list contains a list of int arrays, but the cloned list contains a list of "List" objects. How to solve this issue?

Thanks

AqlaSolutions commented 2 years ago

This happens because subtype information is preserved only when such subtype is registered in the model. Otherwise there is no way to tell which exact type should be created. Currently it doesn't work with array subtypes and this looks like a bug.

A "hacky" solution could be hinting which type you expect:

MetaType outer = model.Add(typeof(List<IList<int>>), true);
outer.SetNestedSettingsWhenRoot(x => x.V.Collection.ConcreteType = typeof(int[]), 1);

But unfortunately this produces an exception if you set ConcreteType to an array because it requires special handling different from just using IList interface. Also you can't use surrogates for repeated types. So there is no workaround for now. If you want an array there just use List<int[]> instead of List<IList<int>>.

If you want to contribute please take a look at ListDecorator, ArrayDecorator classes and usages of the ConcreteType field.

inethui commented 2 years ago

Thanks for the quick response. We'll tweak our classes to work around this issue

AqlaSolutions commented 2 years ago

With the latest release you can specify an array as a ConcreteType for a collection. Also you can instead register an array as a collection subtype with MetaType.AddSubType.