XamlReader.Parse在空String上抛出异常

时间:2010-03-23 18:45:21

标签: c# xaml string xamlreader

在我们的应用程序中,我们需要以propertyName,propertyValue,propertyType的形式将对象的属性保存到同一个数据库表中,而不管对象的类型如何。我们决定使用XamlWriter来保存所有给定对象的属性。然后,我们使用XamlReader加载已创建的XAML,并将其重新转换为属性的值。除了空字符串之外,这在大多数情况下都可以正常工作。 XamlWriter将保存一个空字符串,如下所示。

<String xmlns="clr-namespace:System;assembly=mscorlib" xml:space="preserve" /> 

XamlReader看到这个字符串并尝试创建一个字符串,但是在String对象中找不到要使用的空构造函数,因此它会抛出一个ParserException。

我能想到的唯一解决方法是,如果属性为空字符串,则不实际保存该属性。然后,当我加载属性时,我可以检查哪些不存在,这意味着它们将是空字符串。

是否有一些解决方法,或者有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

在尝试序列化字符串时,我们遇到了类似的问题。我们解决它的唯一方法是创建一个具有适当构造函数的StringWrapper结构或类。然后,我们使用此类型加载并保存字符串值。

答案 1 :(得分:0)

我也遇到了问题,并在网上搜索了一个解决方案,但找不到一个。

我通过检查保存的XML并修复空字符串来解决这个问题(使用XamlWriter的输出提供FixSavedXaml):

    static string FixSavedXaml(string xaml)
    {
        bool isFixed = false;
        var xmlDocument = new System.Xml.XmlDocument();
        xmlDocument.LoadXml(xaml);
        FixSavedXmlElement(xmlDocument.DocumentElement, ref isFixed);
        if (isFixed) // Only bothering with generating new xml if something was fixed
        {
            StringBuilder xmlStringBuilder = new StringBuilder();
            var settings = new System.Xml.XmlWriterSettings();
            settings.Indent = false;
            settings.OmitXmlDeclaration = true;

            using (var xmlWriter = System.Xml.XmlWriter.Create(xmlStringBuilder, settings))
            {
                xmlDocument.Save(xmlWriter);
            }

            return xmlStringBuilder.ToString();
        }

        return xaml;
    }

    static void FixSavedXmlElement(System.Xml.XmlElement xmlElement, ref bool isFixed)
    {
        // Empty strings are written as self-closed element by XamlWriter,
        // and the XamlReader can not handle this because it can not find an empty constructor and throws an exception.
        // To fix this we change it to use start and end tag instead (by setting IsEmpty to false on the XmlElement).
        if (xmlElement.LocalName == "String" &&
            xmlElement.NamespaceURI == "clr-namespace:System;assembly=mscorlib")
        {
            xmlElement.IsEmpty = false;
            isFixed = true;
        }

        foreach (var childElement in xmlElement.ChildNodes.OfType<System.Xml.XmlElement>())
        {
            FixSavedXmlElement(childElement, ref isFixed);
        }
    }