Проблема Сериализация Enum в .NET - PullRequest
0 голосов
/ 16 июля 2010

У меня есть элементарный stumper, использующий сериализацию в приложении ASP.NET 2.0 для класса C #, содержащего свойство enum. Насколько я понимаю, сериализация перечислений поддерживается, если они отображаются в целые числа. Поэтому я не могу понять, почему у меня возникла эта проблема с сериализацией / десериализацией моего перечисления.

Мой код:

[Serializable]
public class Report
{
    public PercentTime paramPercentRange;

    // Constructors
    public Report()
    {
    }
    public Report(PercentTime percentRange)
    {
        paramPercentRange = percentRange;
    }
}

public enum PercentTime
{
    Null = 0,
    ZeroToFivePercent = 1,
    FiveToTenPercent = 2,
    TenToFifteenPercent = 3,
    FifteenToTwentyPercent = 4,
    MoreThanTwentyPercent = 5
}

// Serialize Report to a HiddenField
public void SaveReportObject(Report reportObj, HiddenField hiddenReportObj)
{
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();

    // Seralize Report Object to Binary Format
    formatter.Serialize(stream, reportObj);
    stream.Position = 0;

    // Convert Stream to ASCII Encoding
    StreamReader reader = new StreamReader(stream, Encoding.ASCII);

    // Store Report Object as a Base64 Encoded String in a HiddenField
    hiddenReportObj.Value = Convert.ToBase64String(Encoding.ASCII.GetBytes(reader.ReadToEnd()));

    // Close Streams
    reader.Close();
    stream.Close();
}

public Report GetReportObject(String strBase64)
{
    Report report;
    Stream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    StreamWriter writer = new StreamWriter(stream, Encoding.ASCII);
    writer.AutoFlush = true;
    stream.Position = 0;

    // Convert Base64 String to ASCII encoded Stream
    writer.Write(Encoding.ASCII.GetString(Convert.FromBase64String(strBase64)));
    stream.Position = 0;

    // Deserialze ASCII encoded Stream
    report = (Report)formatter.Deserialize(stream);  // error 

    // Close Streams
    writer.Close();
    stream.Close();

    return report;
}

Я получаю следующую недопустимую ошибку BinaryFormatter:

   at System.Runtime.Serialization.Formatters.Binary.SizedArray.IncreaseCapacity(Int32 index)
   at System.Runtime.Serialization.Formatters.Binary.SizedArray.set_Item(Int32 index, Object value)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
   at Pages_Reports_PercentTimeLobbyingReport.GetReportObject(String strBase64) 

Когда я смотрю на объект потока, его длина равна 287, но позиция равна 282. Первое, что я предполагаю, это проблема не чтения всего потока, но я могу изменить класс Report для хранения перечисления целое число, и это прекрасно работает. Мне очень интересно узнать, в чем здесь проблема.

1 Ответ

5 голосов
/ 16 июля 2010

Ваш поток содержит двоичные данные. Затем вы конвертируете это в ASCII . Это действительно очень плохая идея. Вы потеряете данные. Не делай этого.

Вы делаете кодировку base64, но не в том месте. Вы должны конвертировать первоначально записанные двоичные данные в base64, например как это:

string text = Convert.ToBase64String(stream.ToArray());

Затем, чтобы десериализовать, вы должны конвертировать его наоборот:

IFormatter formatter = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(text))
{
    return (Report)formatter.Deserialize(stream); 
}

Я не знаю, почему это сработало для вас, когда вы использовали int ... но я думаю, что это скорее удача, чем все остальное.

Никогда не пытайтесь читать вывод BinaryFormatter, как если бы это был просто текст.

...