我是 WCF 的新手,希望有人可以提供帮助。我有一个非抽象基类,该基类[knowntype]
与派生类一起应用于它,并在数组中对我的服务的请求正文中使用。当我使用带有派生类的 XML 调用服务时,我在反序列化后得到的所有代码都是基类,而不是派生类。
输入 XML 有一个xsi:type
似乎被完全忽略的 xml 实例类型 ( ) 属性——无论我将其设置为什么,系统都会为我提供没有错误的基类。
我得到的实际代码/等是巨大的。所以,我敲了一个有代表性的测试,但这工作正常,有趣的是,如果我将 更改xsi:type
为无效类型,我会从 中得到一个异常,这DataContractSerializer
与我想要工作的代码不同!
如果我更改元素的名称以强制异常,我会看到提及DataContractSerializer
:
`Start element 'itemz' does not match end element 'item'. Line 110, position 23.
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlUTF8TextReader.ReadEndElement()
at System.Xml.XmlUTF8TextReader.Read()
at System.Xml.XmlBaseReader.Skip()
at System.Runtime.Serialization.XmlReaderDelegator.Skip()
at ReadArrayOfitemFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDe legator reader, String name, String ns, Type declaredType, DataContract& dataContract)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDe legator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadinteropSectionFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
...
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)`
所以,我有点难过:从异常情况来看,看起来它在两种情况下都使用了 DataContractSerializer,但在实际代码中,它甚至没有尝试使用派生类型。与较旧的 ASMX 样式服务不同,我还没有找到一种方法可以跳入序列化程序代码以查看它到底在做什么。我做错了什么,如何调试序列化程序?
如果有任何帮助,我可以尝试提供更多代码/xml。我得到的“演示”代码如下;就像真实的代码一样,它[MessageContract]
为服务使用 a,但实体都是 DataContract 的(在真实的代码中,SVCUTIL 生成了具有相似属性的代理代码)。
[DataContract] public class Security
{
[DataMember] public string Username { get; set; }
}
[DataContract] public class Wrapper
{
[DataMember] public BaseEntity[] MyEntities { get; set; }
}
[DataContract, KnownType(typeof(AdvancedEntity))] public class BaseEntity
{
[DataMember] public string Name { get; set; }
}
[DataContract] public class AdvancedEntity : BaseEntity
{
[DataMember] public int Age { get; set; }
}
[ServiceContract] interface ITrivialService
{
[OperationContract] Response DoStuff(Request request);
}
[MessageContract] public class Request
{
[MessageHeader] public Security AuthenticationDetails { get; set; }
[MessageBodyMember] public Wrapper MyWrapper { get; set; }
}
[MessageContract] public class Response
{
[MessageBodyMember] public BaseEntity Entity { get; set; }
}
public class TrivialService : ITrivialService
{
public Response DoStuff(Request request)
{
string newName = string.Empty;
BaseEntity entity = request.MyWrapper.MyEntities[0];
//do something different depending on which entity we got
AdvancedEntity advancedEntity = entity as AdvancedEntity;
if (advancedEntity != null)
{
advancedEntity.Name = request.AuthenticationDetails.Username;
advancedEntity.Age++;
}
else
{
entity.Name = entity.Name + " and " + request.AuthenticationDetails.Username;
}
Response response = new Response();
response.Entity = entity;
return response;
}
}