【问题标题】:Need to overwrite XMLWriter's method需要覆盖 XMLWriter 的方法
【发布时间】:2020-05-07 04:18:13
【问题描述】:

如果值为空,我需要覆盖 XMLWriter 的方法“WriteElementString”以不写入元素,下面的代码不起作用,尝试 overridenew关键字,但它仍然进入框架方法。

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);
        }
    }
}

【问题讨论】:

标签: c# overriding


【解决方案1】:

您需要创建一个对象来装饰XmlWriter 以实现您想要做的事情。 More on the Decorator Pattern

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 页面上的 Binding Extension Methods at Compile Time 部分编译器将始终将 WriteElementString 解析为由 XmlWriter 实现的实例。您需要手动调用您的扩展方法 XmlWriterExtensions.WriteElementString(writer, localName, value); 才能让您的代码按原样执行。

【讨论】:

  • 我有一个问题,编译器希望我实现原始 XmlWriter 类中可用的所有函数,而且我无法覆盖 WriteElementString,因为它说“无法覆盖......因为它没有标记为虚拟、抽象或覆盖”。
  • 将类抽象化可以解决大部分错误,但仍然无法覆盖 WriteElementString。
  • 好的,我不得不使用“new”而不是“override”。
  • @paul-2011 很好奇WriteElementString 不是virtual。但请注意,使用new 不会使函数调用多态。作为Decorator Pattern 的一部分,您应该实现简单的传递调用,而不是将类标记为抽象类。
  • 我的代码实际上并没有工作,它抛出“InvalidCastException:无法将'System.Xml.XmlWellFormedWriter'类型的对象转换为MyWriter类型”。当我执行“StringBuilder XMLBuilder = new StringBuilder(); XmlWriterSettings XMLSettings = new XmlWriterSettings(); XMLSettings.Encoding = Encoding.UTF8; MyWriter Writer = (MyWriter)MyWriter.Create(XMLBuilder, XMLSettings);”时
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2023-01-07
  • 2012-12-25
  • 2013-08-19
相关资源
最近更新 更多