Why does XmlSerializer require types which inherit

2020-02-10 06:29发布

问题:

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
}

回答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)



回答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.