2017-06-29 1 views
1

Je l'extrait de code suivant écrit dans le noyau .net:Exception en désérialisation XML wtih DataContractSerializer dans .NET de base

using System; 
using System.Runtime.Serialization; 
using System.Text; 
using System.Xml; 

namespace BugTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Hello World!"); 

      var xml = @"<PingDataConfirmation xmlns=""http://mycompany.com/MyProduct/Operations""> 
     <SourceGuid>88c02aba-f78c-4749-8665-0caddee08b8a</SourceGuid> 
     <Guid>88c02aba-f78c-4749-8665-0caddee08b8a</Guid> 
     <CreationTime>0001-01-01T00:00:00</CreationTime> 
     </PingDataConfirmation>"; 

      const int buffSize = 1000000; 

      int bytes = 0; 
      int chars = 0; 
      byte[] result = new byte[buffSize]; 
      bool compl; 
      Encoding.UTF8.GetEncoder().Convert(xml.ToCharArray(), 0, xml.Length, result, 0, buffSize, true, out chars, out bytes, out compl); 

      var xmlReader = XmlDictionaryReader.CreateTextReader(result, 0, bytes, new XmlDictionaryReaderQuotas()); 
      var sr = new DataContractSerializer(typeof(PingDataConfirmation)); 
      var deserialized = sr.ReadObject(xmlReader); 
     } 
    } 

    [DataContract(Namespace = "http://mycompany.com/MyProduct/Operations")] 
    public class PingDataConfirmation 
    { 
     [DataMember(IsRequired = true)] 
     public string SourceGuid { get; set; } 

     [DataMember(IsRequired = true)] 
     public string Guid { get; set; } 

     [DataMember(IsRequired = true)] 
     public DateTime CreationTime { get; set; } 
    } 
} 

Il émet une exception:

System.Runtime.Serialization.SerializationException: Erreur dans la ligne 1 position 86. 'Element' 'SourceGuid' de l'espace de noms 'http://mycompany.com/MyProduct/Operations' n'est pas attendu. élément attendant « CreationTime »

Il semble donc que, DataContractSerialized a raté une des propriétés. Donc, peut-il être bug dans l'implémentation .net de base de DataContractSerializer? Est-il possible de déboguer l'intérieur pour voir pourquoi cela arrive?

csproj:

<Project Sdk="Microsoft.NET.Sdk"> 
    <PropertyGroup> 
    <OutputType>Exe</OutputType> 
    <TargetFramework>netcoreapp1.1</TargetFramework> 
    </PropertyGroup> 
    <ItemGroup> 
    <PackageReference Include="System.ServiceModel.Primitives" Version="*" /> 
    <PackageReference Include="System.ServiceModel.Http" Version="*" /> 
    </ItemGroup> 
</Project> 

noyau .net:

1.0.4 

Répondre

1

Votre problème est que votre data member order est incompatible avec l'ordre des éléments dans le fichier XML.

De Data Member Order:

  • Si un type de contrat de données est une partie d'une hiérarchie d'héritage, les membres de données de ses types de base sont toujours d'abord dans l'ordre. Dans l'ordre, les membres de données du type actuel qui n'ont pas la propriété Order de l'attribut DataMemberAttribute sont classés par ordre alphabétique, par ordre .

  • Vous trouverez ensuite les membres de données qui ont la propriété Order de l'ensemble d'attributs DataMemberAttribute. Celles-ci sont classées par ordre de la propriété Order en premier, puis alphabétiquement s'il ya plus de qu'un membre d'une certaine valeur de Order. Les valeurs de la commande peuvent être ignorées .

Et de Data Contract Equivalence: Data Member Order and Data Contract equivalence:

Gardez à l'esprit que l'ordre des membres de données doivent correspondre et que les membres du type de base précèdent les membres de type dérivé dans l'ordre.

Ainsi soit l'ordre des éléments dans le fichier XML doit être alphabétique ou DataMemberAttribute.Order valeurs doivent être précisées qui sont conformes à l'ordre réel des éléments dans le fichier XML:

[DataContract(Namespace = "http://mycompany.com/MyProduct/Operations")] 
public class PingDataConfirmation 
{ 
    [DataMember(IsRequired = true, Order = 1)] 
    public string SourceGuid { get; set; } 

    [DataMember(IsRequired = true, Order = 2)] 
    public string Guid { get; set; } 

    [DataMember(IsRequired = true, Order = 3)] 
    public DateTime CreationTime { get; set; } 
}