【问题标题】:How can I set up an XmlWriter with the same settings as XmlDictionaryWriter?如何设置与 XmlDictionaryWriter 具有相同设置的 XmlWriter?
【发布时间】:2018-01-25 06:48:19
【问题描述】:

我正在使用

DataContractSerializer dcs = new DataContractSerializer(typeof(T));
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(filestream, Encoding.UTF8);
dcs.WriteObject(xdw, obj);

为了写出 XML,我听说过 WCF DataContractSerializer 在性能和提供前向兼容性方面的优点。

但是,无法将设置传递给 XmlDictionaryWriter。

我不是 100% 理解 XmlDictionaryWriter 和具有自定义设置的普通 XmlWriter 之间的区别,据我所知,不可能调整 XmlDictionaryWriter 的设置。

那么 XmlDictionaryWriter 和 XmlWriter 之间有什么区别(是的,它是一个超类,但我说的是具体的,vs var XmlWriter = XmlWriter.Create(filestream, settings);

除了将缩进设置为 true 之外,我可以使用哪些设置来尽可能接近地模仿 XmlDictionaryWriter?

我现在有

var settings = new XmlWriterSettings
            {
                Indent = true,
                Encoding = Encoding.UTF8,
                IndentChars = "    "
            };

作为我对 XmlWriter 的设置,而 XmlDictionaryWriter 似乎具有 null 设置。 (XmlDictionaryWriter.Settings 既是 null 又是只读的,所以这很失败。)

我的最终目标是格式化 XML,所以如果更改不是太严重,我还是可以使用手动创建的 XmlWriter。

使用 NUnit 比较两者的结果

XmlDictionaryWriter:

"<Party xmlns=\"http://schemas.datacontract.org/2004/07/HeliSTATS.Test\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Guests><Larry><Age>12</Age><Friend><Name>John</Name></Friend></Larry><Larry><Age>15</Age><Friend><Name>Mason</Name></Friend></Larry></Guests></Party>"

XmlWriter:

"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Party xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/HeliSTATS.Test\">\r\n    <Guests>\r\n        <Larry>\r\n            <Age>12</Age>\r\n            <Friend>\r\n                <Name>John</Name>\r\n            </Friend>\r\n        </Larry>\r\n        <Larry>\r\n            <Age>15</Age>\r\n            <Friend>\r\n                <Name>Mason</Name>\r\n            </Friend>\r\n        </Larry>\r\n    </Guests>\r\n</Party>"

【问题讨论】:

  • 您是否考虑过放弃它们并使用来自 Linq 的更现代的 XDocument、XElement 和 XAttribute 类?您是否也有对 WCF 的要求,而不是使用 WebApi2 和 Rest? WebApi2 尊重内容类型标头,因此会将 XML 提供给任何需要它的人,或者将 json 提供给任何需要它的人。
  • 我不知道。我会调查的。由于显式注释和在没有公共属性的情况下工作,我被 DataContractSerializer 所吸引。
  • WebApi2 和 Rest 要求人们在那里编写自己的结果接口,但 WebApi2 在构建它们方面非常巧妙,您可以注释您的实体,轻松做中间件,并在 PostMan 等中轻松测试它们。这就是我喜欢做事的方式。我创建了一个 API,然后创建了一个类库,它是调用该 Api 的“客户端”,或者我在 Angular 或 Vue 中有一个通过 Ajax 请求调用 API 的 JS 层。今天制作的几乎每一个现代 API 都是 REST。
  • 感谢您的提示,我目前正在将它用于一些超级简单的配置,这就是为什么我关心缩进,关于限制可见性修饰符。我不确定为 REST 设计的东西会有多合适,但 DCS 似乎还不错。
  • 对于大型 xml 文件,我会坚持使用 XmlWriter,这样您就可以一次保存文件的一小部分。我使用 XmlWriter writer.WriteRaw(string) 组合了 XmlWriter 和 XDocument。然后将可能的 XElement 对象转换为字符串 object.ToString()。在 Xml 顶部的少数情况下,我必须使用 StartElement 和 EndElement。

标签: c# .net xml wcf


【解决方案1】:

您实际上是在问几个单独的问题:

  1. XmlDictionaryWriterXmlWriter 有什么区别?

    XMLWriter vs XMLDictionaryWriter 解决了这个问题,BronumskiMike McCaughan 提供了答案。结论是XmlDictionaryWriter被使用了

    • 为了性能(虽然我们不确定),并且
    • 作为数据协定的 XML、二进制和 MTOM 序列化的抽象基类。


    此外,DataContractSerializer 的某些功能仅适用于XmlDictionaryWriter。例如。如果您需要使用custom DataContractResolver 序列化对象,则需要使用DataContractSerializer.WriteObject(XmlDictionaryWriter, Object, DataContractResolver),因为没有WriteObject() 的重载需要XmlWriterDataContractResolver

  2. 如何使用XmlDictionaryWriter 并控制XmlWriterSettings

    如果您确定需要使用XmlDictionaryWriter(出于性能原因,或者因为您需要使用DataContractResolver),那么您可以使用XmlDictionaryWriter.CreateDictionaryWriter(XmlWriter) 构造一个包装预先存在的XmlWriter

  3. 我可以使用哪些设置来尽可能地模仿XmlDictionaryWriterXmlWriter,同时仍然缩进?

    你没有。您使用您需要的那个,如果您需要两者的功能,请创建一个包装好的XmlWriter,如上所示。

综上所述,以下扩展方法可用于序列化XmlDictionaryWriter 和可选XmlWriterSettings

public static partial class DataContractSerializerExtensions
{
    public static string ToContractXml<T>(this T obj, DataContractSerializer serializer = null, XmlWriterSettings settings = null, DataContractResolver resolver = null)
    {
        serializer = serializer ?? new DataContractSerializer(obj == null ? typeof(T) : obj.GetType());
        using (var textWriter = new StringWriterWithEncoding((settings == null ? null : settings.Encoding) ?? Encoding.UTF8))
        {
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                serializer.WriteObject(xmlWriter, obj, resolver);
            }
            return textWriter.ToString();
        }
    }

    public static void WriteObject(this DataContractSerializer serializer, Stream stream, object obj, XmlWriterSettings settings, DataContractResolver resolver = null)
    {
        if (serializer == null || stream == null)
            throw new ArgumentNullException();
        // If settings are specified create a wrapped dictionary writer, else create a text writer directly.
        if (settings == null)
        {
            // Let caller close the stream
            using (var xmlWriter = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8, false))
            {
                serializer.WriteObject(xmlWriter, obj, resolver);
            }
        }
        else
        {
            using (var xmlWriter = XmlWriter.Create(stream, settings))
            {
                serializer.WriteObject(xmlWriter, obj, resolver);
            }
        }
    }

    static void WriteObject(this DataContractSerializer serializer, XmlWriter xmlWriter, object obj, DataContractResolver resolver)
    {
        if (serializer == null || xmlWriter == null)
            throw new ArgumentNullException();
        using (var xmlDictionaryWriter = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter))
        {
            serializer.WriteObject(xmlDictionaryWriter, obj, resolver);
        }
    }
}

然后,分析带有和不带有 XmlWriterSettingsWriteObject(),以确定使用包装的 XmlWriter 对性能的影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多