修复WCF循环引用序列化

时间:2012-08-09 18:01:47

标签: c# wcf serialization

我有课:

[Serializable]
[System.Runtime.Serialization.DataContract(IsReference = true)]
public class SymbolElem
{
    public SymbolElem() // Constructor
    {
        Children = new List<SymbolElem>();
    }

    public List<SymbolElem> Children { get; set; }
    public string Name { get; set; }
}

我想要一个使用命名管道返回SymbolElem的服务。一开始我以为我遇到了错误,因为我返回了很多对象。

无论如何,这里是服务的方法:

public SymbolElem TestMethod()
{
     Common.SymbolElem root = new Common.SymbolElem() {
             Name="root"
     };

     Common.SymbolElem child = new Common.SymbolElem() {
                    Name = "child"
     };                   

     root.Children.Add(child);

     return root;
}

这样可行,但当我做的事情如下:

public SymbolElem TestMethod()
{
     Common.SymbolElem root = new Common.SymbolElem() {
             Name="root"
     };

     Common.SymbolElem child = new Common.SymbolElem() {
                    Name = "child"
     };                   

     root.Children.Add(child);
     child.Children.add(root);   // <------------ this causes an exception after returning s1!!!!

     return root;
}

以下是例外情况:

System.ServiceModel.Dispatcher.NetDispatcherFaultException was unhandled
  Message=The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetSymbolsResult. The InnerException message was ''EndElement' 'SymbolElem' from namespace 'http://schemas.datacontract.org/2004/07/SymbolFileParser.Common' is not expected. Expecting element '_x003C_BitOffset_x003E_k__BackingField'.'.  Please see InnerException for more details.
  Source=mscorlib
  Action=http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault
  StackTrace:
    Server stack trace: 
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameter(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
       at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
       at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
       at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
       at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at ConsoleApplication4.ServiceReference1.ISymbolFileParser.GetSymbols(String filePath)
       at ConsoleApplication4.ServiceReference1.SymbolFileParserClient.GetSymbols(String filePath) in C:\Users\Antonio\Desktop\SymbolFileParser\ConsoleApplication4\Service References\ServiceReference1\Reference.cs:line 371
       at ConsoleApplication4.Program.Main(String[] args) in C:\Users\Antonio\Desktop\SymbolFileParser\ConsoleApplication4\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.Runtime.Serialization.SerializationException
       Message='EndElement' 'SymbolElem' from namespace 'http://schemas.datacontract.org/2004/07/SymbolFileParser.Common' is not expected. Expecting element '_x003C_BitOffset_x003E_k__BackingField'.
       Source=System.Runtime.Serialization
       StackTrace:
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.ThrowRequiredMemberMissingException(XmlReaderDelegator xmlReader, Int32 memberIndex, Int32 requiredIndex, XmlDictionaryString[] memberNames)
            at ReadSymbolElemFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
            at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
            at ReadArrayOfSymbolElemFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
            at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
            at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
            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)
            at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
            at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
       InnerException: 

1 个答案:

答案 0 :(得分:2)

问题是DataContractSerializer不知道如何处理循环引用。 您可以在父级上指定IsRefernce属性。如上所述here