2

ジェネリック インターフェイスを実装しようとすると、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 プロパティが使用されるようです。

関数名を明示的に設定するにはどうすればよいですか、または少なくともどうすれば合法的なものにすることができますか?

4

1 に答える 1

2

コンパイル可能な出力を取得するには、次を使用しますImplementationTypes: コードを 1 行変更しただけです (ただし、参照用に単純な行と修正済みの行を含めます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 および4.0では_対応することを忘れています。メソッド名は、実装されているインターフェースのメソッド名と比較して個別にオーバーライド可能である必要があることを指摘するなど、Connect でバグをログに記録することはおそらく価値があります。`(Of <type>)

PrivateImplementationType非ジェネリックをサポートするには、の機能が必要なようですGetEnumerator。これは、元のコードを単純に調整して、単一のコンパイル可能なライブラリを生成するもので、空のコードに関する警告のみがありますmethod.Attributes = MemberAttributes.Privateこのコードには、使用されている場所が無視されるなど、まだ「問題」がPrivateImplementationTypeあります...

于 2012-10-20T09:00:45.693 に答える