質問

って感じは、その答えは"いき"さんでショッ---私はunenviableの位置を変更すると、レガシー VB6アプリが強化のに変換するスマートな言語ではないオプションです。このアプリに依存してのユーザ定義型のデータを移動させます。私のように共通の機能で参照できるよう、このような種類のデータを含んでいます。
疑似コードは、"わらびもち"をここでは私が求めていたもの:

Public Sub PrintUDT ( vData As Variant )
  for each vDataMember in vData
    print vDataMember.Name & ": " & vDataMember.value 
  next vDataMember 
End Sub

どうやら、この情報ニーズをご利用になCOMどこか---他のVB6達がケアを。

おかげさ

役に立ちましたか?

解決

に反してどれを取得できることが実行時の型情報UDTのVB6(ではありませんが内蔵言語)。Microsoftの TypeLib情報オブジェクト図書館 (tlbinf32.dllることができるプログラムに検査COMタイプの情報を実行します。すべてこのコンポーネントの場合Visual Studioを設置:追加するには、既存のVB6プロジェクトは、 プロジェクト->参照 チェックを入"のTypeLib情報"といいます。 りますのでご注意して配信登録tlbinf32.dll お申し込みの設定です。

見学もできるUDTインスタンスを使用TypeLib情報コンポーネント実行時にないとしてUDTの宣言 Public 定義内 Public クラスです。このために必要があくVB6生COM対応タイプ情報をご利用いただける、UDTのできる列挙の各種クラスのTypeLib情報コンポーネント).最も簡単な方法はこの要件を満足するために、きめえてくださるということは、UDTの公 UserTypes クラスを作成し、ActiveX DLLまたはActiveX EXE.

概要の作業例

この例では三つのパーツ:

  • 第1部:作ActiveX DLLプロジェクトを含んでいるのUDTの宣言
  • 第2部:作成例 PrintUDT 方法などを実際に体感できる列挙の分野のUDTインスタンス
  • 第3部:作成したい反復子のクラスで簡単に繰り返し処理を実行しの分野によって公UDT、フィールドの名前と値です。

作業例

第1部:のActiveX DLL

先ほどもお話したように、必要なものにUDTの公共アクセスのための列挙しているTypeLib情報。ここがれているUDTの公共のクラス内のActiveX DLLまたはActiveX EXEます。他のプロジェクトのお申し込みが必要なアクセスUDTのを参照のこの新しいコンポーネント.

に従うとこの例では、新たなActiveX DLLプロジェクトの名前で UDTLibrary.

次に、名前の変更を Class1 クラスのモジュール(この値はデフォルトでは、IDE) UserTypes 追加につユーザ定義型の授業 PersonAnimal:

' UserTypes.cls '

Option Explicit

Public Type Person
    FirstName As String
    LastName As String
    BirthDate As Date
End Type

Public Type Animal
    Genus As String
    Species As String
    NumberOfLegs As Long
End Type

上場1: UserTypes.cls 行為としてのコンテナ当社のUDTの

次に、変更の Instancing 性のための UserTypes クラス"の2PublicNotCreatable".理由はありませんでインスタンスを生成するの UserTypes クラスを直接では単なるとして、公共コンテナ当社のUDTです。

最後に、確認し Project Startup Objectプロジェクト->プロパティ)の設定を"なし"のプロジェクトのコンパイル.現時点ですべてのファイルを保存し、新規ファイルと呼ばれ UDTLibrary.dll.

第2部列挙UDT型情報

このように利用できまTypeLibオブジェクト図書館を実施する PrintUDT 方法。

まず、新たな標準EXEプロジェクトと呼んでい合わせてご利用いただけます。追加の参照ファイルへの UDTLibrary.dll 作成された第1部.以来ていただきたいと思い姿を見せるこの作品は使用いたしますのウィンドウの試験をコードします。

新しいモジュールの作成、名前で UDTUtils は、下記コードを追加します:

'UDTUtils.bas'
Option Explicit    

Public Sub PrintUDT(ByVal someUDT As Variant)

    ' Make sure we have a UDT and not something else... '
    If VarType(someUDT) <> vbUserDefinedType Then
        Err.Raise 5, , "Parameter passed to PrintUDT is not an instance of a user-defined type."
    End If

    ' Get the type information for the UDT '
    ' (in COM parlance, a VB6 UDT is also known as VT_RECORD, Record, or struct...) '

    Dim ri As RecordInfo
    Set ri = TLI.TypeInfoFromRecordVariant(someUDT)

    'If something went wrong, ri will be Nothing'

    If ri Is Nothing Then
        Err.Raise 5, , "Error retrieving RecordInfo for type '" & TypeName(someUDT) & "'"
    Else

        ' Iterate through each field (member) of the UDT '
        ' and print the out the field name and value     '

        Dim member As MemberInfo
        For Each member In ri.Members

            'TLI.RecordField allows us to get/set UDT fields:                 '
            '                                                                 '
            ' * to get a fied: myVar = TLI.RecordField(someUDT, fieldName)    '
            ' * to set a field TLI.RecordField(someUDT, fieldName) = newValue ' 
            '                                                                 '
            Dim memberVal As Variant
            memberVal = TLI.RecordField(someUDT, member.Name)

            Debug.Print member.Name & " : " & memberVal

        Next

    End If

End Sub

Public Sub TestPrintUDT()

    'Create a person instance and print it out...'

    Dim p As Person

    p.FirstName = "John"
    p.LastName = "Doe"
    p.BirthDate = #1/1/1950#

    PrintUDT p

    'Create an animal instance and print it out...'

    Dim a As Animal

    a.Genus = "Canus"
    a.Species = "Familiaris"
    a.NumberOfLegs = 4

    PrintUDT a

End Sub

上場2:一例 PrintUDT 方法及び簡易試験方法

第3部:でオブジェクト指向

上記の事例を"クイックや汚れ込んだ"デモンストレーションの利用方法のTypeLib情報オブジェクト図書館列挙の分野のUDT.実世界シナリオ"という作 UDTMemberIterator クラスのようにしていますが、簡単に繰り返し処理を実行して分野のUDTは、ユーティリティ機能モジュールを生成する UDTMemberIterator 指定されたUDTインスタンス.ることができるようになるには、次のようなものがコードでは、より近くの擬似コードをご掲載のご質問

Dim member As UDTMember 'UDTMember wraps a TLI.MemberInfo instance'

For Each member In UDTMemberIteratorFor(someUDT)
   Debug.Print member.Name & " : " & member.Value
Next

はじめて投稿してみましにくいものになることができま再利用のコードから PrintUDT ルーチンで作成した第2部

まず、新規作成しActiveXプロジェクトの名前で UDTTypeInformation か何かに似ています。

次のことを確認してください起動オブジェクトのための新しいプロジェクトの設定を"なし".

にまずは簡単なラッパークラスの動作の詳細 TLI.MemberInfo クラスから呼び出しのコードで簡単にUDTのフィールドの名前と値です。呼んだときのこのクラス UDTMember.の Instancing 物件のためにこのクラス PublicNotCreatable.

'UDTMember.cls'
Option Explicit

Private m_value As Variant
Private m_name As String

Public Property Get Value() As Variant
    Value = m_value
End Property

'Declared Friend because calling code should not be able to modify the value'
Friend Property Let Value(rhs As Variant)
    m_value = rhs
End Property

Public Property Get Name() As String
    Name = m_name
End Property

'Declared Friend because calling code should not be able to modify the value'
Friend Property Let Name(ByVal rhs As String)
    m_name = rhs
End Property

上場3:の UDTMember ラッパークラス

今を創出していく必要がありま序で繰り返し処理する反復子のクラス UDTMemberIterator, るために使用のVB For Each...In 構文に対して繰り返し処理を実行する分野のUDTインスタンス.の Instancing 物件のためにこのクラスに設定することが望 PublicNotCreatable したことについて定義の設定ユーティリティメソッド以降をインスタンスを代表呼び出します。

編集: (2/15/09と思い洗浄、コードモーターパラグライダーです。

'UDTMemberIterator.cls'

Option Explicit

Private m_members As Collection ' Collection of UDTMember objects '


' Meant to be called only by Utils.UDTMemberIteratorFor '
'                                                       '
' Sets up the iterator by reading the type info for     '
' the passed-in UDT instance and wrapping the fields in '
' UDTMember objects                                     '

Friend Sub Initialize(ByVal someUDT As Variant)

    Set m_members = GetWrappedMembersForUDT(someUDT)

End Sub

Public Function Count() As Long

    Count = m_members.Count

End Function

' This is the default method for this class [See Tools->Procedure Attributes]   '
'                                                                               '
Public Function Item(Index As Variant) As UDTMember

    Set Item = GetWrappedUDTMember(m_members.Item(Index))

End Function

' This function returns the enumerator for this                                     '
' collection in order to support For...Each syntax.                                 '
' Its procedure ID is (-4) and marked "Hidden" [See Tools->Procedure Attributes]    '
'                                                                                   '
Public Function NewEnum() As stdole.IUnknown

    Set NewEnum = m_members.[_NewEnum]

End Function

' Returns a collection of UDTMember objects, where each element                 '
' holds the name and current value of one field from the passed-in UDT          '
'                                                                               '
Private Function GetWrappedMembersForUDT(ByVal someUDT As Variant) As Collection

    Dim collWrappedMembers As New Collection
    Dim ri As RecordInfo
    Dim member As MemberInfo
    Dim memberVal As Variant
    Dim wrappedMember As UDTMember

    ' Try to get type information for the UDT... '

    If VarType(someUDT) <> vbUserDefinedType Then
        Fail "Parameter passed to GetWrappedMembersForUDT is not an instance of a user-defined type."
    End If

    Set ri = tli.TypeInfoFromRecordVariant(someUDT)

    If ri Is Nothing Then
        Fail "Error retrieving RecordInfo for type '" & TypeName(someUDT) & "'"
    End If

    ' Wrap each UDT member in a UDTMember object... '

    For Each member In ri.Members

        Set wrappedMember = CreateWrappedUDTMember(someUDT, member)
        collWrappedMembers.Add wrappedMember, member.Name

    Next

    Set GetWrappedMembersForUDT = collWrappedMembers

End Function

' Creates a UDTMember instance from a UDT instance and a MemberInfo object  '
'                                                                           '
Private Function CreateWrappedUDTMember(ByVal someUDT As Variant, ByVal member As MemberInfo) As UDTMember

    Dim wrappedMember As UDTMember
    Set wrappedMember = New UDTMember

    With wrappedMember
        .Name = member.Name
        .Value = tli.RecordField(someUDT, member.Name)
    End With

    Set CreateWrappedUDTMember = wrappedMember

End Function

' Just a convenience method
'
Private Function Fail(ByVal message As String)

    Err.Raise 5, TypeName(Me), message

End Function

上場4:の UDTMemberIterator クラスです。

るということに注意してくださのためにこのクラスのlistで For Each 使用できます設定の手順属性の Item_NewEnum 方法として注目のコードのコメント).の変更ができます手順の属性からツールメニュー(ツール->手続きの属性).

また、ユーティリティ機能(UDTMemberIteratorFor の非常に最初のコード例ではセージを作成する、 UDTMemberIterator UDTの場合インスタンス、またそれに対し繰り返し操作を行うと For Each.新しいモジュールの作成という Utils メモリの使用範囲のサイズは以下のコード:

'Utils.bas'

Option Explicit

' Returns a UDTMemberIterator for the given UDT    '
'                                                  '
' Example Usage:                                   '
'                                                  '
' Dim member As UDTMember                          '
'                                                  '        
' For Each member In UDTMemberIteratorFor(someUDT) '
'    Debug.Print member.Name & ":" & member.Value  '
' Next                                             '
Public Function UDTMemberIteratorFor(ByVal udt As Variant) As UDTMemberIterator

    Dim iterator As New UDTMemberIterator
    iterator.Initialize udt

    Set UDTMemberIteratorFor = iterator

End Function

上場5:の UDTMemberIteratorFor 光機能です。

最後に、プロジェクトのコンパイルや新規プロジェクトを作成したテストです。

お試projet追加-新たに作成された UDTTypeInformation.dllUDTLibrary.dll 作成された第1部としては、下記コードを新しいモジュール:

'Module1.bas'

Option Explicit

Public Sub TestUDTMemberIterator()

    Dim member As UDTMember

    Dim p As Person

    p.FirstName = "John"
    p.LastName = "Doe"
    p.BirthDate = #1/1/1950#

    For Each member In UDTMemberIteratorFor(p)
        Debug.Print member.Name & " : " & member.Value
    Next

    Dim a As Animal

    a.Genus = "Canus"
    a.Species = "Canine"
    a.NumberOfLegs = 4

    For Each member In UDTMemberIteratorFor(a)
        Debug.Print member.Name & " : " & member.Value
    Next

End Sub

上場6:試験の UDTMemberIterator クラスです。

他のヒント

@Dan、

それはあなたがUDTのRTTIを使用しようとしているように見えます。私はあなたが本当に実行時前にUDTについて知らなくても、その情報を得ることができるとは思いません。 あなたが始められるようにしてください:


この反射機能を持たないので。私は自分のUDTに自分のRTTIを作成することになります。

あなたのベースラインを得ました。これを試してください:

Type test
    RTTI as String
    a as Long
    b as Long 
    c as Long
    d as Integer
end type

あなたはすべてのソースファイルを開き、UDTの型の名前でRTTIを追加するユーティリティを書くことができます。おそらく共通のファイル内のすべてのUDTを配置する方が良いでしょう。

RTTIは、このようなものになるだろう

"文字列:ロング:ロング:ロング:整数"

あなたが値を抽出することができますUDTのメモリを使用します。

あなたがクラスにすべてのタイプを変更した場合。あなたは選択肢を持っています。クラスのタイプから変更の大きな落とし穴は、あなたが新しいkeyworldを使用しなければならないことです。そこたびに型変数の宣言は、新しいを追加します。

次に、バリアントキーワードまたはCallByNameを使用することができます。 VB6は、反射のANYTYPEを持っていませんが、あなたは、有効なフィールドのリストを作ることができ、それらは例えば存在しているかどうかをテスト

クラスのテストがあり、次の

Public Key As String
Public Data As String

あなたはその後、次の操作を行うことができます。

Private Sub Command1_Click()
    Dim T As New Test 'This is NOT A MISTAKE read on as to why I did this.
    T.Key = "Key"
    T.Data = "One"
    DoTest T
End Sub

Private Sub DoTest(V As Variant)
    On Error Resume Next
    Print V.Key
    Print V.Data
    Print V.DoesNotExist
    If Err.Number = 438 Then Print "Does Not Exist"
    Print CallByName(V, "Key", VbGet)
    Print CallByName(V, "Data", VbGet)
    Print CallByName(V, "DoesNotExist", VbGet)
    If Err.Number = 438 Then Print "Does Not Exist"
End Sub

あなたが存在しないフィールドを使用しようとする場合は、438が発生しますエラー。 CallByNameは、クラスのフィールドやメソッドを呼び出すために文字列を使用することができます。

何VB6新は非常に興味深く、非常にこの変換のバグを最小化するよう、あなたが薄暗い宣言時に行います。あなたはこれを見る

Dim T as New Test

タグとまったく同様に扱われていません
Dim T as Test
Set T = new Test
たとえば、これは動作します。

Dim T as New Test
T.Key = "A Key"
Set T = Nothing
T.Key = "A New Key"

これはエラーになります。

Dim T as Test
Set T = New Test
T.Key = "A Key"
Set T = Nothing
T.Key = "A New Key"

この理由は、第1の例示的VB6フラグにTがそう部材がそれをアクセスされるいつでもTが何もないかどうかを確認することです。それがある場合には、自動的にテストクラスの新しいインスタンスを作成し、変数を割り当てます。

第2の例ではVBは、この動作を追加しません。

ほとんどのプロジェクトでは、我々は、厳密に確認してください、我々はテスト、セットT =新しいテストとして点心Tを行かせます。しかし、あなたのケースでは、新しいテストが進むべき道であるとして、薄暗いTを使用して、副作用の最小量を持つクラスに型を変換したいからです。新しいとして点心が変数の型がより密接に動作する方法を模倣する原因となるためです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top