通过CodeDom实现通用接口

时间:2012-10-18 20:42:10

标签: vb.net generics codedom

当我尝试实现通用接口时,CodeDom没有为我生成合法的VB。

这是我生成VB代码的VB代码。

Private Sub RunTest()

    Dim compileUnit = New CodeCompileUnit

    Dim ns As New CodeNamespace()
    compileUnit.Namespaces.Add(ns)
    ns.Imports.Add(New CodeNamespaceImport("System"))
    ns.Imports.Add(New CodeNamespaceImport("System.Collections.Generic"))

    Dim fooCollection = New CodeTypeDeclaration("FooCollection")
    ns.Types.Add(fooCollection)
    fooCollection.TypeAttributes = Reflection.TypeAttributes.Public
    fooCollection.IsClass = True
    fooCollection.BaseTypes.Add(New CodeTypeReference(GetType(System.Object)))
    fooCollection.BaseTypes.Add(New CodeTypeReference( _
        "System.Collections.Generic.IEnumerable" _
        , New CodeTypeReference() {New CodeTypeReference("Foo")} _
    ))

    Dim method = New CodeMemberMethod
    fooCollection.Members.Add(method)
    method.Attributes = MemberAttributes.Private
    method.Name = "GetEnumerator"
    method.ReturnType = New CodeTypeReference( _
        "System.Collections.Generic.IEnumerable" _
        , New CodeTypeReference() {New CodeTypeReference("Foo")} _
    )
    method.PrivateImplementationType = New CodeTypeReference( _
        "System.Collections.Generic.IEnumerable" _
        , New CodeTypeReference() {New CodeTypeReference("Foo")} _
    )

    Dim provider = New Microsoft.VisualBasic.VBCodeProvider
    Dim options = New Compiler.CodeGeneratorOptions
    Dim writer = New IO.StringWriter
    provider.GenerateCodeFromCompileUnit(compileUnit, writer, options)
    Console.WriteLine(writer.ToString)

End Sub

这会产生:

Public Class FooCollection
    Inherits Object
    Implements System.Collections.Generic.IEnumerable(Of Foo)

    Function System_Collections_Generic_IEnumerable`1_GetEnumerator() _
    As System.Collections.Generic.IEnumerable(Of Foo) _
    Implements System.Collections.Generic.IEnumerable(Of Foo).GetEnumerator

    End Function

End Class

问题是函数的名称。函数名称中的刻度标记不适用于合法的函数名称。

似乎在使用CodeMethodMethod的PrivateImplentationType属性时,Name属性将被用作您正在实现的方法的名称,而不是函数的名称。

您如何明确设置功能名称,或者至少如何使其成为合法的?

1 个答案:

答案 0 :(得分:2)

要获得可编辑的输出,只需使用ImplementationTypes:我刚刚更改了一行代码(但我提供了一条简单的参考线以及更正后的ReturnType):

method.Name = "GetEnumerator"
method.ReturnType = New CodeTypeReference( _
    "System.Collections.Generic.IEnumerator" _
    , New CodeTypeReference() {New CodeTypeReference("Foo")} _
)
method.ImplementationTypes.Add(New CodeTypeReference( _
    "System.Collections.Generic.IEnumerable" _
    , New CodeTypeReference() {New CodeTypeReference("Foo")} _
))

使用PrivateImplementationType似乎没有简单的解决方法。 Microsoft Microsoft.VisualBasic.VBCodeGenerator.GenerateMethod中的代码(位于Friend类中,因此不容易被覆盖)适用于.,并将其替换为_,但忘记了` .NET 2.0-3.5中的1}}和4.0中的(Of <type>)。可能值得在Connect上记录一个错误,包括指出方法名称应该与正在实现的接口上的方法名称相比可以单独覆盖。

您似乎需要PrivateImplementationType的功能来支持非通用GetEnumeratorHere是我对原始代码的简单调整,以生成单个可编译库,仅显示有关空代码的警告。此代码仍有“问题”,例如method.Attributes = MemberAttributes.Private在使用PrivateImplementationType时被忽略...