Vb.net 通过CodeDom实现通用接口

Vb.net 通过CodeDom实现通用接口,vb.net,generics,codedom,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.Imp

当我尝试实现一个通用接口时,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的PrivateImplementationType属性时,Name属性被用作正在实现的方法的名称,而不是函数的名称


如何明确设置函数名,或者至少如何使其合法化?

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

使用
PrivateImplementationType
似乎没有简单的解决方法。Microsoft在
Microsoft.VisualBasic.VBCodeGenerator.GenerateMethod
(位于
Friend
类中,因此不容易重写)中的代码满足
,将其替换为
,但忘记满足.NET 2.0-3.5中的
`
和4.0中的
(Of)
。在Connect上记录一个bug可能是值得的,包括指出与正在实现的接口上的方法名相比,方法名应该是单独可重写的


您似乎需要
PrivateImplementationType
的功能来支持非泛型
GetEnumerator
。这是我对原始代码的简单调整,以生成单个可编译库,其中只包含关于空代码的警告。此代码仍然存在“问题”,例如在使用
PrivateImplementationType
时忽略
method.Attributes=MemberAttributes.Private

分配给Name属性的顺序没有影响。总结我以前(现在已删除)的注释:设置
.Name
的顺序不重要;私有的
GetBaseTypeOutput
无条件地在
Name
前面加上前缀,但是它在.NET Framework 4中包含了对
“`”c
的逻辑检查,但是这仍然会产生引用
系统集合\u泛型\u IEnumerable(Of Foo)\u GetEnumerator
的错误代码!这无助于解决问题,但您的返回类型应该是
“System.Collections.Generic.IEnumerator”
。非常感谢!经验教训:将非泛型类型分配给PrivateImplementationType,但将泛型类型使用ImplementationTypes.Add()。这并不像那样简单。对于非泛型类型,我也会使用
ImplementationTypes
,除非我必须做一些不同的事情,就像这里的情况一样,因为我看不到如何使用VB的特性,即方法名与它正在实现的接口中的方法名不相同。
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")} _
))