需要重写XMLWriter的方法

5
我需要重写XMLWriter的方法“WriteElementString”,如果值为空则不写入元素,下面的代码无效,尝试了“override”和“new”关键字,但仍然会跳转到框架方法。
public static void WriteElementString(this XmlWriter writer,
                                      string localName,
                                      string value)
{
    if (!string.IsNullOrWhiteSpace(value))
    {
        writer.WriteStartElement(localName);
        writer.WriteString(value);
        writer.WriteEndElement();
    }
}

答案很接近,但正确的解决方案是:
public abstract class MyWriter : XmlWriter
{
    private readonly XmlWriter writer;
    public Boolean skipEmptyValues;

    public MyWriter(XmlWriter writer)
    {
        if (writer == null) throw new ArgumentNullException("Writer");
        this.writer = writer;
    }

    public new void WriteElementString(string localName, string value)
    {
        if (string.IsNullOrWhiteSpace(value) && skipEmptyValues)
        {
            return;
        }
        else
        {
            writer.WriteElementString(localName, value);
        }
    }
}

1
你实际上不能直接覆盖静态方法。至少不是直接的。这里有一个关于类似问题的好问题/答案:https://dev59.com/fHI95IYBdhLWcg3w-C9b - Leron
1个回答

7
你需要创建一个对象来装饰 XmlWriter 以实现你想要做的事情。有关装饰器模式的更多信息
public class MyXmlWriter : XmlWriter
{
    private readonly XmlWriter writer;

    public MyXmlWriter(XmlWriter writer)
    {
        if (writer == null) throw new ArgumentNullException("writer");
        this.writer = writer;
    }

    // This will not be a polymorphic call
    public new void WriteElementString(string localName, string value)
    {
        if (string.IsNullOrWhiteSpace(value)) return;

        this.writer.WriteElementString(localName, value);
    }

    // the rest of the XmlWriter methods will need to be implemented using Decorator Pattern
    // i.e.
    public override void Close()
    {
        this.writer.Close();
    }
    ...
}

在LinqPad中使用上述对象。
var xmlBuilder = new StringBuilder();
var xmlSettings = new XmlWriterSettings
{
    Indent = true
};

using (var writer = XmlWriter.Create(xmlBuilder, xmlSettings))
using (var myWriter = new MyXmlWriter(writer))
{
    // must use myWriter here in order for the desired implementation to be called
    // if you pass myWriter to another method must pass it as MyXmlWriter
    //    in order for the desired implementation to be called
    myWriter.WriteStartElement("Root"); 
    myWriter.WriteElementString("Included", "Hey I made it");
    myWriter.WriteElementString("NotIncluded", "");
}

xmlBuilder.ToString().Dump();

输出:

<?xml version="1.0" encoding="utf-16"?>
<Root>
  <Included>Hey I made it</Included>
</Root>

你试图使用扩展方法覆盖一个方法,这不是它们的本意。请参见扩展方法MSDN页面上的编译时绑定扩展方法部分。编译器总是将WriteElementString解析为XmlWriter实现的实例。你需要手动调用你的扩展方法XmlWriterExtensions.WriteElementString(writer, localName, value);以使你的代码按照你的意愿执行。

我有一个问题,编译器要求我实现原始XmlWriter类中所有可用的函数,而且我无法重写WriteElementString,因为它说“无法重写...因为它没有标记为virtual、abstract或override”。 - paul-2011
1
我的代码实际上没有运行,它抛出了“InvalidCastException: 无法将类型为'System.Xml.XmlWellFormedWriter'的对象强制转换为'MyWriter'类型。” 当我执行“StringBuilder XMLBuilder = new StringBuilder(); XmlWriterSettings XMLSettings = new XmlWriterSettings(); XMLSettings.Encoding = Encoding.UTF8; MyWriter Writer = (MyWriter)MyWriter.Create(XMLBuilder, XMLSettings);”时。 - paul-2011
1
@paul-2011,你没有正确创建MyWriter。在使用“装饰者模式”时,你首先要实例化一个XmlWriter的实例,然后将其提供给装饰器的构造函数。 - JG in SD
1
如果它仍然没有提供可工作的代码,为什么这被接受为答案呢? - Wolfgang Roth
@WolfgangRoth 上述代码并不是一个完整的示例,它存在一些空缺。直接复制粘贴无法编译。如果您遇到问题,应该发布一个问题,社区将乐意提供帮助。 - JG in SD
显示剩余3条评论

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