继承类上的XDocument加载-无法强制转换



也许我用错了方法,但是在我遇到这个问题之前,它似乎是实现我的需求的一种相当优雅的方法,我有一堆基于xpath的代码来修改word文档。它很旧了,我正在升级它,使它更易于管理,同时增加一些额外的功能。

我想,创建一个DocxDocument类并让它继承XDocument类是有意义的,这样我就可以使用System.Xml.Linq和System.Xml.Xpath来编辑底层的xml文档。

我错误地认为,如果XDocument继承了DocXDocument的类型,它可以被强制转换为DocXDocument。那么,看看下面的代码我到底是如何将XDocument加载到DocXDocument的呢?

Public Class DocXDocument2
    Inherits XDocument
    Public Sub New()
        MyBase.New()
    End Sub
    Public Overloads Function Load(DocumentPath As String) As XDocument
        Using pkg = WordprocessingDocument.Open(DocumentPath, True)
            Return XDocument.Load(pkg.MainDocumentPart.GetStream())
        End Using
    End Function
End Class

我只是希望能够像这样加载文档:

dim docx = DocXDocument.load("C:temp.docx")

最好的方法是:不要覆盖XDocument。您应该在XDocument周围创建一个包装器,该包装器存储对已加载文档的引用,并允许您以自己想要的方式访问它。我强烈建议这样做。

你的类可以像这样:

Public Class DocXDocument2
    Private ReadOnly _doc As XDocument
    Private Sub New(doc As XDocument)
        _doc = doc
    End Sub
    Public Shared Function Load(DocumentPath As String) As XDocument
        Using pkg = WordprocessingDocument.Open(DocumentPath, True)
            Return New DocXDocument2(XDocument.Load(pkg.MainDocumentPart.GetStream()))
        End Using
    End Function
    Public Function Descendants As IEnumerable(Of XElement)
        Return _doc.Descendants 
    End Function
End Class

注意,原来的XDocument将加载函数暴露为Shared函数。所以我在这里修改了

无论如何,有一种方法可以通过继承来完成它。但它并不漂亮。您必须使用Shadow的load方法来强制使用您的方法,并且必须使用XDocument的Copy-Constructor来正确地获取文档。它可以是这样的:

Public Class DocXDocument2
    Inherits XDocument
    Private Sub New(doc As XDocument)
        MyBase.New(doc)
    End Sub
    Public Shared Shadows Function Load(DocumentPath As String) As XDocument
        Using pkg = WordprocessingDocument.Open(DocumentPath, True)
            Return New DocXDocument2(XDocument.Load(pkg.MainDocumentPart.GetStream()))
        End Using
    End Function
End Class

这只是为了尽可能接近你的方法。我建议使用第一种方法。它是更简洁的代码,并且可以让您更好地控制对文档做什么和不做什么。继承XDocument毕竟会将XDocument的每一个public方法暴露给使用你的类的人。

对于你最初的问题,为什么XDocumentDocXDocument2的转换失败。原因很简单,XDocument.Load函数创建的是XDocument,而不是DocXDocument2。可以很容易地将特定类的实例强制转换为由该对象实现的任何类或接口。但是您不能将它强制转换为缩小特定对象实现范围的对象。您必须将实例构造为DocXDocument2来获得这种类型的实例。

最新更新