locked
How to serialize System.Collections.Generic.IList?

    Question

  • Does anyone know if there is a way to serialize a System.Collections.Generic.IList? I'm receiving the following exception,
    Cannot serialize interface System.Collections.Generic.IList`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]. 
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
    
    Exception Details: System.NotSupportedException: Cannot serialize interface System.Collections.Generic.IList`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].
    when I try to do something like the following.
    [WebMethod]
    public IList<string> GenericTest()
    {
        IList<string> l = new List<string>();
        l.Add("string #1");
        return l;
    }
    However, if I use the non-generic IList interface, it works just fine. Normally, I would just use a System.Collections.Generic.List instead, but, what I'm trying to serialize is a domain object that I use with NHibernate. i.e. you can't use List, you have to use an IList because NHibernate will assign it's own IList implementation for you.
    [WebMethod]
    public System.Collections.IList NonGenericTest()
    {
        System.Collections.IList l = new System.Collections.ArrayList();
        l.Add("string #1");
        return l;
    }
    Wednesday, April 26, 2006 5:48 PM

Answers

All replies

  • try this...

       
    Code Snippet

       public class StringList:IList<string>
        {
            public StringList():base(){}
        }

        [WebMethod]
        public StringList GenericTest()
        {
            StringList l = new StringList();
            l.Add("string #1");
            return l;
        }

    Wednesday, July 25, 2007 5:25 PM
  • There isn't a good workaround for this unfortunately.  There's some suggestions here:

     

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1376732&SiteID=1

    Thursday, August 23, 2007 7:52 PM
    Moderator
  • Is this limitation by design or an oversight? As a rule, I try to use interfaces when possible in my public APIs to allow more flexibility in implementation, but this one's had me fretting for a while now. At a minimum, I'd like to have the ability to catch the error ala OnUnknownElement/Attribute to perform custom handling but right now, I tend to use a custom serializer (that functions closer to XAML but without the WindowsBase dependency), as most of my (de)serialization is for configuration purposes that don't require strict adherence to XmlSerializer's rules.

    Also, I'm aware that WinFX (yeah, that's right, I'm calling it WinFX Smile ) includes its own serializers, but the catch with those is that those require dependencies to WCF/WPF (same gripe I have with ObservableCollection, a supremely useful class that's unfortunately wedged into a UI assembly) whereas System.Xml is "free" so to speak

    Wednesday, May 14, 2008 2:57 PM
  • I'm not convinced you've thought this through.

     

    There is no such thing as an IList. IList is an interface: it is a contract that some class must implement. IList is still a contract, only it specifies that "T" will be "string". But it is a contract, not an implementation.

     

    Each implementation of IList has its own properties and fields. Each of them would serialize differently from the others. Consider:

     

    Code Snippet

    public class AList : IList<string>

    {

    // ... IList<string> implementation, then

    private int _prop;

    public int SomePropertyINeed {get {return _prop;} set {_prop = value;}}

    }

     

    public class BList : IList<string>

    {

    // ... IList<string> implementation, then

    private string _prop;

    public string SomePropertyINeed {get {return _prop;} set {_prop = value;}}

    }

     

     

    An instance of the first class would serialize an int. The second would serialize a string.

     

    When it's time to deserialize, how would a caller know which class had been serialized? Would the caller even know about the two classes?

     

    It just makes no sense to talk about serializing interfaces. When an IList<something> is serialized, you're actually serializing an array of the something. Any code that does that assumes that the only thing that matters about the IList is the fact that it's a list of something. If the implementation mattered at all, it would be completely lost.

    Saturday, May 17, 2008 7:09 PM
    Moderator
  • I'm not asking the serializer to instantiate the interface, because collections should be instantiated by the owning class (which is why they don't have settors). All I want the serializer to do is to add items to the collection, not create the collection first, so why should the serializer care what about implementation details of the list? This is different from non-collections, but that's why there is a completely different property standard for lists than for atomic properties.

    Saturday, May 17, 2008 7:32 PM
  • The job of the serializer is to serialize and deserialize objects. Why should it treat "collections" any differently from other objects? Why should it even know what a collection is?

    Saturday, May 17, 2008 7:45 PM
    Moderator
  • If the job of the serializer was to just serialize and deserialize, then it would have a problem with all collections given that they shouldn't be deserialized anyway (remember, there is an FxCop rule that collections should be read-only, with the owning class providing the instance rather than the consumer). However it does deserialize read-only collections fine, even if it can't do the instantiation itself. In fact, it can deserialize ILists just fine; it just can't do generic IList<T>s, and the point I've been trying to make is: what is so special about IList<T> that the serializer cannot deserialize items into it?

    Saturday, May 17, 2008 8:41 PM
  • Serializing an IList is perfectly reasonable. In fact it works if you use WCF. It doesn't work with ASMX web services and Microsoft said they weren't going to fix it. Note, it does work with non-generic IList with ASMX, just not the generic version.

    Saturday, May 17, 2008 9:00 PM
  • There's no point in arguing about this. The behavior is by design. By bad design, in my opinion. Undocumented special cases are a bad idea and an indication that there's something wrong with the design. This is one of those areas where Microsoft compromised good design in favor of making an easy out of the box experience for developers who want to think of XML Web Services as a simple, transparent RPC mechanism. In my opinion, the design succeeds for those developers and fails everyone else.

     

    It fails people who expect their .NET-specific members will be translated to the other side (notice - only default constructors; no indexers; no events; no methods get translated into client proxy classes). And it fais anyone who assumes that this is a good design.

     

    As an experiment, I tried the "read-only IList" case, but tried something non-trivial with it:

     

    Code Snippet

    [Serializable]

    [XmlInclude(typeof(List<ProcessResultsNameValuePair>))]

    public class ProcessDetailsList

    {

        public ProcessDetailsList()

        {

            _details = new List<ProcessResultsNameValuePair>();

            _details.Add(

                new ProcessResultsNameValuePair(

                    Enumeration.AgencyCode, "Value"));

        }

     

        private readonly List<ProcessResultsNameValuePair> _details;

     

        [XmlElement("Details")]

        public IList Details

        {

            get {return _details;}

        }

     

        public void Add(

            ProcessResultsNameValuePair item)

        {

            _details.Add(item);

        }

    }

     

     

    What will the result be when this is deserialized? Can you tell from reading the code? Is it easily explained? Does it make sense?

    Saturday, May 17, 2008 10:21 PM
    Moderator
  • Don't anyone argue with an MVP, they always know best. I think maybe you need to talk to the Java web service folks also because support for generic interfaces in their "bad design" has always worked. And evidently Microsoft didn't think it was bad design since they made it work for WCF.

    Saturday, May 17, 2008 10:42 PM
  • I didn't say don't argue with me; I said I saw no point in arguing about it. That's different.

     

    Also, Java and .NET are two different platforms. What makes sense in one may not make any sense in the other.

     

    Is the Java XML Serialization mechanism one-for-one the same as the .NET mechanism? I don't know, which is why I wasn't discussing it. In fact, I believe this is the first time in this thread that Java has been brought up at all. Perhaps you're thinking of a different thread on a similar subject where I did ask about Java?

    Saturday, May 17, 2008 10:51 PM
    Moderator