Why does XmlSerializer require types which inherit from IEnumerable to have an implementation of Add(System.Object)?

10,281

Solution 1

Because sub classes implicitly implement interface methods because of the base class but xmlserializer is using reflection and that is why you get the error at runtime and not compile time.

Try explicitly implementing and see what happens. I have not had this issue before so I'm not sure why you are unless you're doing something custom.

If you have your sub classes explicitly implementing the interface but not doing any implementation code (letting the implicit implementation of methods happen) then remove the interface from your sub type declaration as it should still be valid due to your base type. (someone tell me if i'm off here)

Solution 2

I've just run into this issue and solved it by adding an add method:

public class EffectOptions : IEnumerable<EffectOption>
{
    public List<EffectOption> Options { get; private set; }

    public void Add(object o){
        this.Options.Add(o as EffectOption); //you may want to extend the code to check that this cast can be made,
                                             //and throw an appropriate error (otherwise it'll add null to your list)
    }

    //IEnumerable methods
}

I hope this helps.

Share:
10,281
Joan Venge
Author by

Joan Venge

Professional hitman.

Updated on June 17, 2022

Comments

  • Joan Venge
    Joan Venge almost 2 years

    I am using xml serialization but now came across a runtime error I haven't seen before.

    "To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy. ImageEditor.EffectOptions does not implement Add(System.Object)"

    It seems a little weird to be forced to implement a method via runtime exception, rather than compile time error such as missing methods from implemented interfaces.

    Is this by design? Should this not be enforced via some sort of interface like XmlSerializable, etc?

    Other than this I am wondering if the serializer guarantees passing a value of the right type where I can just cast it to the type, which in my case is EffectOption.

    Or should I implement this Add (object) method to see if the object is of type EffectOption and if not throw an exception?

    I haven't implemented this Add (object) method before but my guess is it's safer to just cast it to EffectOption and add it to EffectOptions collection.

    EDIT: Here's the type itself:

    public class EffectOptions : IEnumerable<EffectOption>
    {
        public List<EffectOption> Options { get; private set; }
    
        //IEnumerable methods
    }
    
  • Joan Venge
    Joan Venge about 13 years
    Thanks but what do you mean by subclasses? My type isn't derived from any other type, it just implements IEnumerable.
  • Dustin Davis
    Dustin Davis about 13 years
    Can you post the class with method stubs?
  • Dustin Davis
    Dustin Davis about 13 years
    Why not declare your class as public class EffectOptions : List<EffectOption> ? It would solve your issue. I assume you didn't go this way for design reasons.
  • Joan Venge
    Joan Venge about 13 years
    Thanks, if I do that, then I inherit all the functionality of Lists, right? I want the Options to be simple and not exposed. It only lets you to create and enumerate the values, so it's pretty basic.
  • Dustin Davis
    Dustin Davis about 13 years
    It will do the same thing you are doing now just without the options property. IMO this is how I would go if you want to implement a custom collection (and this IS what I do). Options is a list anyway you're just preventing the setting of the reference.
  • Dustin Davis
    Dustin Davis about 13 years
    If all you're doing is wrapping a list then this is a good way to go. You don't need to do any extra work to implement IEnumerable because List already does it. Unless there is something that you're trying to accomplish, this looks like the way to go.
  • Joan Venge
    Joan Venge about 13 years
    Yes but if I do that, then the Options collection is exposed. I don't want people to be able to modify the options stored in any instance of EffectOptions. But there they could just do EffectOptions[1] = ..., etc. Also I use List for this example, but I might want to switch to another collection internally. If you inherit from List, then it's gonna be harder, no?
  • Dustin Davis
    Dustin Davis about 13 years
    Inherit from ICollection then, not IEnumerable and even though you have private set; anyone can still add items to the list. You're only making the reference private set. Use ReadOnlyCollection instead. You have options set as public which exposes it already so why even bother inheriting from ICollection or IEnumerable in the first place?
  • Joan Venge
    Joan Venge about 13 years
    Thanks you are right, it's public currently. I did it to create a temporary options file by adding options manually in code. But it the actual code, it's private. That's what I was basing my opinions.
  • Dustin Davis
    Dustin Davis about 13 years
    check out this link to a blog post i made which wraps ienumerable<>. It will give you some clue as to which way to go. programmersunlimited.wordpress.com/2011/01/08/… I just wrap the list methods so it still does all the work.