Why does XmlSerializer require types which inherit from IEnumerable to have an implementation of Add(System.Object)?
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.
Comments
-
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 typeEffectOption
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 toEffectOption
and add it toEffectOptions
collection.EDIT: Here's the type itself:
public class EffectOptions : IEnumerable<EffectOption> { public List<EffectOption> Options { get; private set; } //IEnumerable methods }
-
Joan Venge about 13 yearsThanks but what do you mean by subclasses? My type isn't derived from any other type, it just implements IEnumerable.
-
Dustin Davis about 13 yearsCan you post the class with method stubs?
-
Dustin Davis about 13 yearsWhy 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 about 13 yearsThanks, 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 about 13 yearsIt 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 about 13 yearsIf 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 about 13 yearsYes 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 about 13 yearsInherit 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 about 13 yearsThanks 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 about 13 yearscheck 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.