2016-02-17 3 views
0

Я нашел странное поведение с XmlSerializer в C#, кто-то мне помогает? Я хочу этот XML в SOAP/MTOM, и мне нужно ХОР: Включить вне любой другой XMLElement:Ошибка XmlSerializer, массив байтов, список и InvalidOperationException

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xop:Include href="cid:http://tempuri.org/1/635913361387292553" xmlns:xop="http://www.w3.org/2004/08/xop/include"/> 
    <List>1</List> 
    <List>2</List> 
</Root> 

Вот мой C# код:

public static void Main(string[] args) 
{ 
    var simulatedFile = new byte[800]; 
    new Random().NextBytes(simulatedFile); 
    var root = new Root {List = new List<string> {"1","2"}, Bytes = simulatedFile}; 

    XmlSerializer ser = new XmlSerializer(typeof(Root)); 
    using (var mtomInMemory = new MemoryStream()) 
    { 
     using (var writer = XmlDictionaryWriter.CreateMtomWriter(mtomInMemory, Encoding.UTF8, int.MaxValue, string.Empty)) 
     { 
      ser.Serialize(writer, root); 
     } 
     Console.WriteLine(Encoding.UTF8.GetString(mtomInMemory.ToArray())); 
    } 

    Console.Read(); 
} 
public class Root 
{ 
    [XmlText] 
    public byte[] Bytes { get; set; } 
    [XmlElement] 
    public List<string> List { get; set; } 
} 

Ошибка у меня есть:

«System.InvalidOperationException» произошел в System.Xml.dll. Здесь был ошибкой, отображающей тип «Program.Root». Невозможно сериализовать объект типа 'Program.Root'. Рассмотрим изменение типа элемента XmlText 'Program.Root.Bytes' из System.Byte [] в строку или массив строк.

Но мне нужно, чтобы мой Bytes массив содержит файл бинарного, потому что с MTOM, он будет сериализуются CreateMtomWriter в base64, если длина составляет менее 768 байт или в XOP: Включите если более 768 байт.

Я хочу, чтобы он был закодирован как прямой ребенок Корневого Элемента, не обернутый каким-либо другим Элементом.

Если в классе Root я помещаю только свойство Bytes или List, оно работает отлично, но если я ставлю оба, это не так.

+0

Каков ваш ожидаемый результат? Где бы вы хотели, чтобы этот байтовый массив был закодирован? –

ответ

0

От Microsoft: Благодарим за сообщение об этой проблеме. Это по дизайну. Массив байтов не может быть текстовым. Попробуйте решить эту проблему e.г. используя строку.

1

Возможно, вы столкнулись с ошибкой XmlSerializer.

Если я изменить класс удалить в List свойство, например, так:

public class Root 
{ 
    [XmlText] 
    public byte[] Bytes { get; set; } 
} 

Тогда XmlSerializer будет сериализовать успешно с массивом байтов автоматически представляется в виде базы 64 строки:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">AAECAwQFBgcICQ==</Root> 

И вместо этого, если я изменю класс, чтобы свойство XmlText было string -значным прокси-ресурсом, которое переводит массив байтов от и базировать 64, то XmlSerializer будет снова сериализации успешно и одинаково:

public class Root 
{ 
    [XmlIgnore] 
    public byte[] Bytes { get; set; } 

    [XmlText] 
    public string Base64Bytes 
    { 
     get 
     { 
      return Bytes == null ? null : Convert.ToBase64String(Bytes); 
     } 
     set 
     { 
      Bytes = value == null ? null : Convert.FromBase64String(value); 
     } 
    } 

    [XmlElement] 
    public List<string> List { get; set; } 
} 

Действительно, документация XmlTextAttribute.DataType ясно указывает на то, что массивы байтов являются одним из типов данных, поддерживаемых [XmlText]. Neverthess, сочетание свойства [XmlText] byte [] Byte { get; set; } с любым другим свойством [XmlElement] в том же классе приводит к тому, что конструктор XmlSerializer создает исключение. Вы можете захотеть report a problem to Microsoft, так как нет причин для этого не работать.

В то же время вы можете использовать обходное свойство свойства прокси-объекта с строкой, как показано выше.