问题
I am building my own framework to wrap the interfaces exposed via Microsoft.Office.Interop.
I wrap Office-wide functionalities into a first set of interfaces, which are then inherited by a second set of functionalities, which are application-dependent.
Here is a simplified version:
Region "Office Wrappers"
Interface IApplication(Of T As IFile(Of IVariable))
Property Files As IList(Of T)
End Interface
Interface IFile(Of T As IVariable)
Property Variables As IList(Of T)
End Interface
Interface IVariable
End Interface
#End Region
#Region "Word Wrappers"
Interface IWordApp 'ERROR BC32044
Inherits IApplication(Of IWordDocument(Of IVariable, IWordParagraph))
End Interface
Interface IWordDocument(Of TVar As IVariable, TPara As IWordParagraph)
Inherits IFile(Of TVar)
Property Paragraphs As TPara
End Interface
Interface IWordVariable
Inherits IVariable
End Interface
Interface IWordParagraph
End Interface
#End Region
The above sample returns an error (see 'ERROR BC32044 comment in the sample):
Type argument 'IWordDocument(Of IWordVariable, IWordParagraph)' does not inherit from or implement the constraint type 'IFile(Of IVariable)'.
In order to fix this, I need to replace IWordVariable by IVariable in two instances:
Interface IWordApp
Inherits IApplication(Of IWordDocument(Of IVariable, IWordParagraph)) '<- Replacement 1 of 2 here
End Interface
Interface IWordDocument(Of TVar As IVariable, TPara As IWordParagraph) '<- Replacement 2 of 2 here
Inherits IFile(Of TVar)
Property Paragraphs As TPara
End Interface
Since IWordVariable inherits from IVariable, I though AnyGeneric(Of T as IVariable) should accept AnyGeneric(Of IWordVariable).
Why does the original code not compile, and how can I fix this?
Additional information & question
I use generics first because each application (Word, Excel, etc) relies on a set of base interfaces (as explained above), but also because I then "extend" each wrapper to expose some custom functionalities. For example:
Interface IExtendedWordDocument
Inherits IWordDocument(Of IWordVariable, IExtendedWordParagraph)
End Interface
Interface IExtendedWordParagraph
Inherits IWordParagraph
Sub SomeCustomActionHere()
End Interface
Having this system of inheritance allows me to unit test my extended wrappers, whilst I am not too worried about the stability of the Office and Word wrappers, as they basically are a mirror of Microsoft.Office.Interop.
Once developing my models, I was hoping to be able to refer to MyApp As IApplication or As IWordApp, where they would implicitly mean As IApplication(Of IFile(Of IVariable)) or As IWordApp(Of IWordDocument(Of IWordVariable, IWordParagraph)). How could I achieve this?
I did try this:
Interface IApplication
Inherits IApplication(Of IFile(Of IVariable))
End Interface
Interface IWordApp
Inherits IWordApp(Of IWordDocument(Of IWordVariable, IWordParagraph))
End Interface
But for casting to work properly (when passing an IWordApp where an IApplication is expected), I need to have IWordApp(Of IWordDocument(Of IWordVariable, IWordParagraph)) to inherit IApplication instead of IApplication(Of IFile(Of IVariable)), which results in Me.Variables to expose IVariable, not IWordVariable.
When in reality the cascade of generics looks more like this: IWordApp(Of IDocument(Of IVariables(Of IVariable)), IDocuments(Of IDocument(Of IVariables(Of IVariable)))), you then understand why I am trying to cut the code required within the models.
来源:https://stackoverflow.com/questions/58202355/cascading-generic-interfaces