将一个对象序列化成XML文件时抛出异常。

4

我查看了多个问题,但没有一个答案有帮助。我试过使用多个流对象(StreamWriterFileStream)。我还试过使用XmlWriterXmlSerializer等方法。

以下是我的代码:

namespace FacebookPlusPlus
{
    internal static class AppConfig
    {
        public static string AccessToken
        {
            get { return s_SerializableConfig.m_AccessToken; }
            set { s_SerializableConfig.m_AccessToken = value; }
        }

        public static bool AutoConnect
        {
            get { return s_SerializableConfig.m_AutoConnect; }
            set { s_SerializableConfig.m_AutoConnect = value; }
        }

        public static string ErrorMessage { get; set; }

        private const string k_ConfigFilePath = "AppConfig.xml";
        private static SerializableConfig s_SerializableConfig = new SerializableConfig();

        [Serializable]
        public class SerializableConfig
        {
            public string m_AccessToken;
            public bool m_AutoConnect;
        }

        public static bool ExportConfig()
        {
            bool exportSucceed = false;
            try
            {
                using (StreamWriter writer = new StreamWriter(File.Open(k_ConfigFilePath, FileMode.Create)))
                {
                    XmlSerializer serializer = new XmlSerializer(s_SerializableConfig.GetType());
                    serializer.Serialize(writer, s_SerializableConfig);
                }

                exportSucceed = true;
            }
            catch (Exception exception)
            {
                ErrorMessage = exception.Message;
                if (File.Exists(k_ConfigFilePath))
                {
                    File.Delete(k_ConfigFilePath);
                }
            }

            return exportSucceed;
        }

        public static bool ImportConfig()
        {
            bool importSucceed = false;
            if (File.Exists(k_ConfigFilePath))
            {
                try
                {
                    using (Stream stream = File.Open(k_ConfigFilePath, FileMode.Open))
                    {
                        XmlSerializer serializer = new XmlSerializer(s_SerializableConfig.GetType());
                        s_SerializableConfig = (SerializableConfig)serializer.Deserialize(stream);
                    }

                    importSucceed = true;
                }
                catch (Exception exception)
                {
                    importSucceed = false;
                    ErrorMessage = exception.Message;
                }
            }

            return importSucceed;
        }
    }
}

这是异常:

There was an error generating the XML document.
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces)
   at FacebookPlusPlus.AppConfig.ExportConfig() in c:\\...\\AppLogic\\AppConfig.cs:line 48

在出现错误时,字段 AccessToken 包含一个长字符串,而 AutoConnect 包含的是 true

1
你能同时检查被抛出异常中是否有任何“InnerException”错误吗?在使用XmlSerializer时,这些内部异常通常包含相关信息。 - Chris Sinclair
2
这是XmlSerializer已知的一个bug/"限制"。请参见如何序列化静态类的非静态子类。解决方法是取消嵌套类或使用DataContractSerializer,或使外部类为非静态但具有抛出异常的私有构造函数。 - dbc
@dbc,谢谢。看到我的回答了。 - Doron Cohen
2个回答

1

好的,我按照 @dbc 建议的做法进行了操作,并将 AppConfig 设为公共属性,移除了其静态属性并隐藏了其构造函数。效果很好!

仍然对 C# 的奇怪限制感到沮丧,这让我花费了几个小时才理解。而且我讨厌解决方案

namespace FacebookPlusPlus
{
    public class AppConfig
    {
        ...

        [Serializable]
        public class SerializableConfig
        {
            public string m_AccessToken;
            public bool m_AutoConnect;
        }

        private AppConfig() 
        {
            throw new InvalidOperationException("AppConfig Ctor Invoked");
        }

        ...
    }
}

0

当您调用Serealize方法时,您指定的第一个参数可能是问题的根本原因:

在xmlWriter参数中,指定一个从抽象XmlWriter类派生的对象。XmlTextWriter派生自XmlWriter。

在您的情况下,您正在使用StreamWriter,而不是XmlWriter。

来源:https://msdn.microsoft.com/en-us/library/10y9yyta(v=VS.110).aspx

编辑:由于您已经尝试了上述方法,但它没有解决您的问题,像Chris Sinclair所说,尝试获取内部异常。以下代码片段可能有所帮助:

public void SerializeContainer( XmlWriter writer, Container obj )
{
  try
  {
    // Make sure even the construsctor runs inside a
    // try-catch block
    XmlSerializer ser = new XmlSerializer( typeof(Container));
    ser.Serialize( writer, obj );
  }
  catch( Exception ex )               
  {                                   
    DumpException( ex );             
  }                                   
}
public static void DumpException( Exception ex )
{
  Console.WriteLine( "--------- Outer Exception Data ---------" );        
  WriteExceptionInfo( ex );
  ex = ex.InnerException;                     
  if( null != ex )               
  {                                   
    Console.WriteLine( "--------- Inner Exception Data ---------" );                
    WriteExceptionInfo( ex.InnerException );    
    ex = ex.InnerException;
  }
}
public static void WriteExceptionInfo( Exception ex )
{
  Console.WriteLine( "Message: {0}", ex.Message );                  
  Console.WriteLine( "Exception Type: {0}", ex.GetType().FullName );
  Console.WriteLine( "Source: {0}", ex.Source );                    
  Console.WriteLine( "StrackTrace: {0}", ex.StackTrace );           
  Console.WriteLine( "TargetSite: {0}", ex.TargetSite );            
}

来源:https://msdn.microsoft.com/zh-cn/library/Aa302290.aspx


1
他们表示尝试了 XmlWriter 但没有成功。此外,StreamWriter 是有效的输入,因为它继承自 TextWriter,可以与 此重载的 Serialize 一起使用。 - Chris Sinclair
哎呀,他们一开始就提到了这个。 - gmalla
是的,我确实尝试过。为什么将一个对象序列化为 XML 如此困难呢?看起来 .NET 应该允许您将一些数据转换为字符串。 - Doron Cohen
1
谢谢 @gmalla,问题已解决。 - Doron Cohen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接