Search code examples
c#jil

Jil.DeserializationException : Error occurred building a deserializer in redis cache


I'm using Redis Cache using Stack Exchange library.

I used cloudStructure library to use Redis Dictionary and Redis List.

Problem is when I try to retrieve values and if that model has a null value for one list property it is throwing me below exception -

Jil.DeserializationException : Error occurred building a deserializer for TestMainClass: Expected a parameterless constructor for System.Collections.Generic.ICollection1[TestChildClass] ---- Jil.Common.ConstructionException : Expected a parameterless constructor for System.Collections.Generic.ICollection1[TestChildClass]

public class TestMainClass
    {
        public TestMainClass();
        public int Id { get; set; }
        public virtual ICollection<TestChildClass> Mydata { get; set; }
        public string Title { get; set; }
    }


      public class TestChildClass
    {
        public TestChildClass();
        public int Id { get; set; }
        public string Value { get; set; }
    }

Redis code for retrieve value:

RedisDictionary<int, TestMainClass> dictionary = 
new RedisDictionary<int, TestMainClass>("localhost", "mylocaldictionary");
var result = await dictionary.Get(121);

What If I could not able to convert ICollection < T > into List < T >?


Solution

  • It might be a nice feature if the serialization library detected interfaces like ICollection<T> and IList<T> and implemented them with the concrete List<T> during deserialization, but ultimately: every feature needs to be thought of, considered (impact), designed, implemented, tested, documented and supported. It may be that the library author feels this is a great idea and should be implemented; it might not be high on the author's list, but they'd be more than happy to take a pull request; or there might be good reasons not to implement it.

    In the interim, as a general rule that will solve virtually every serialization problem you will ever encounter with any library:

    • the moment the library doesn't work perfectly with your domain model: stop serializing your domain model - use a DTO instead

    By which, I mean: create a separate class or classes that are designed with the specific choice of serializer in mind. If it wants List<T>: then use List<T>. If it wants public fields: use public fields. If it wants the types to be marked [Serializable]: mark the types [Serializable]. If it wants all type names to start with SuperMagic: then start the type name with SuperMagic. As soon as you divorce the domain model from the serialization model, all the problems go away. In addition: you can support multiple serializers in parallel, without getting into the scenario that A needs X and doesn't work with Y; B needs Y and doesn't work with X.

    All you then need to do is write a few lines of code to map between the two similar models (or use libraries that do exactly that, like AutoMapper).