Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
421 views
in Technique[技术] by (71.8m points)

c# - type xxxx not expected use xmlinclude or soapinclude

I have a curious case of this serialization issue - which has been asked many times on this site and I have gone through a few of these questions and tried the usual items to no avail:

  • Add [XmlInclude] to the class throwing the error
  • Remove namespaces
  • Add a different namespace to each class

To explain further, I have provided a simplified version of my code below. Essentially I am using a WebServiceHost object to run a RESTful service and one of my endpoints returns an object serialized as XML (I have annotated the object with [DataContract] and [DataMember] attributes). This object contains a SerializableDictionary<string, object> (here) where the value has been typed as object. I believe this is why it is failing:

  • Works fine when the value is assigned a primitive
  • When I assign a custom object to the KV pair V, I get the unexpected type exception probably because the Serializer does not know how to serilaize the object / some sort of namespacing issue

Obviously, I am unable to annotate Object.cs with [XmlInclude] and because it is a service and I am not myself serializing I cannot using something like

new Serializer(typeof(...), new Type[] { ... }}

Any idea's of what I can do? I thought about not typing the dict value as object and rtaher comething more concrete but the problem is that this value can take primitives or cusotm types. Some code to explain the above:

Edit: Updated the code below to make it more clear

[DataContract]
public class ResponseObject
{
    [DataMember(Name = "data")]
    public SerializableDictionary<string, object> Data { get;set; }

    public ResponseObject()
    {
        Data = new SerializableDictionary<string, object>();
    }
}

...

var d1 = new ResponseObject();
d1.Data.Add("some key", "some value"); //WORKS AND SERIALIZES PERFECLTY

var d2 = new ResponseObject();
d2.Data.Add("some other key", new SomeOtherObjecT());
var d3 = new ResponseObject();
d3.Data.Add("another key", d2);  //THIS THROWS THE UNEXPECTED TYPE ERROR WHEN SEIRLAIZING SomeOtherObject

Edit: The error is thrown in SerializableDictionary where it is attempting to serialize an object of type ResponseObject. The two are in seperate projects - if that is significant?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Normally, you should add an [XmlInclude] to the ResponseObject class. In this case, it doesn't work because of the SerializableDictionary that you're using. That class creates another XmlSerializer in its implementation, and therefore it doesn't care about your [XmlInclude]'s. Basically it just cannot handle your use case. You should switch from the XmlSerializer to the DataContractSerializer which handles the Dictionary class and supports the [KnownType] attribute to register additional types: http://pastebin.com/vGLSaxHF . Also note that it's pointless to add [DataContract] and [DataMember] attributes in your current case because the XmlSerializer ignores those attributes, they are used by the DataContractSerializer only. Or if you're not sure how to change your serializer (I know I'm not) then you should either not be using a Dictionary or change the SerializableDictionary implementation to handle the dynamic object types that you want to use (find every line where it creates a new XmlSerializer). Or, as an alternative, define a base class for all your objects that you will ever put into the dictionary and do it like this:

[XmlInclude(typeof(Class1), XmlInclude(typeof(Class2)), etc]
public class AbstractBase { }

public class Class1 : AbstractBase { ... }

public class Class2 : AbstractBase { ... }

public class BigClass {
    public SerializableDictionary<string, AbstractBase> Dictionary { get; set; }
}

This way, when the SerializableDictionary creates its own XmlSerializer, it will recognize the AbstractBase and from there, all of its descendants.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...