(for Internet Explorer)
← ▼ ▲
↑
get_ObjectsFromFile
(src)
Sub get_ObjectsFromFile( GetFuncs as string or Array of Function,
InterfaceName as string, out_Objs as Array of Object )
静的オブジェクト・スクリプトファイルをすべて取得して一覧できるようにします。
【引数】
GetFuncs
InterfaceName
スクリプトのパス、または include_objs の out_GetFuncs
Empty または、取得するオブジェクトが持つインターフェース
out_Objs
取得したオブジェクトの配列
get_ObjectsFromFile "Lib\*_obj.vbs", "ClassI", m_Objs '// [out] m_Objs
サンプル： インクルードと同時に、静的オブジェクトを取得する
include_objs "Lib\*_obj.vbs", Empty, m_CreateFuncs '// [out] m_CreateFuncs
get_ObjectsFromFile m_CreateFuncs, "ClassI", m_Objs '// [out] m_Objs
サンプル： インクルードした後で、静的オブジェクトを取得する（ファイルを走査しない）
Sub get_StaticObjects( InterfaceName, out_Obj )
If IsEmpty( InterfaceName ) or InterfaceName = "ClassI" Then
Set out_Obj = get_ClassA()
ElseIf InterfaceName = "ClassI2" Then
out_Obj = Array( get_ClassA(), get_ClassB() )
End If
End Sub
静的オブジェクトを一覧できるようにするには、それぞれのスクリプトで、get_StaticObjects
関数を定義する必要があります。 get_ObjectsFromFile や include_objs は、別のスクリプト
ファイルであれば、同じ関数名でも異なる関数インスタンスになります。
→ get_StaticObjects : 静的オブジェクト
参考
→ T_GetObject.vbs [T_IncludeObjs2] [T_IncludeObjs3]
テスト
← ▼ ▲
new_X
→ 名前参照 (vbsool)
参考
Function new_X( Name as string ) as object
文字列で指定した名前のクラスのオブジェクトを生成します。
Function new_ClassA()
Set new_ClassA = new ClassA
End Function
機能的には、"new_" + Name の関数を呼び出すだけなので、別途関数を用意する必要があります。
たとえば、Name = "ClassA" なら、new_ClassA の関数が呼ばれます。
(src)
ただし、多くの場合、get_Object の方が適していることが多いので、get_Object を使うことを検討
してください。
→ get_Object
サンプル：
Dim obj : Set obj = new_X( "ClassA" )
引数は、なしにしてください。
← ▼ ▲
include_objs
Sub include_objs( Wildcard as string, Flags as Empty, out_GetFuncs as Array of Funcion )
静的オブジェクト・スクリプトファイルをインクルードします。
【引数】
Wildcard
Flags
スクリプトファイルのパス、またはフォルダパス
Empty を指定してください
out_GetFuncs
Empty、または、静的オブジェクトを取得する関数の集合
out_CreateFuncs が Empty ではないときのサンプル
include_objs は、インクルードのみ行います。 オブジェクトの生成は、new で生成するか、
get_ObjectsFromFile で行います。
(src)
サンプル： Lib フォルダをインクルードして、その中で定義された ClassA オブジェクトを生成する。
include_objs "Lib\*_obj.vbs", Empty, Empty
Set obj : Set obj = new ClassA : ErrCheck
→ new_X_array
Flags = Empty かつ out_GetFuncs = Empty なら、include で代用できます。
関連
→ include
out_GetFuncs は、静的オブジェクトを取得する関数の集合です。 get_ObjectsFromFile の第1引数
に渡すと、文字列を渡したときより高速に処理します。
→ T_GetObject.vbs [T_IncludeObjs1c]
テスト
→ T_GetObject.vbs [T_IncludeObjs3]
→ T_GetObject.vbs [T_IncludeObjsMulti]
→ T_GetObject.vbs [T_IncludeObjsMulti_NoWild]
→ T_GetObject.vbs [T_IncludeObjsEmptyArray]
← ▼ ▲
get_DefineInfoObject
Sub get_DefineInfoObject( in_out_Object as DefineInfoClass, FullPath as string )
単純な DefineInfo オブジェクトを生成します。
→ DefineInfo プロパティ (vbsool)
参考
DefineInfo オブジェクトに FullPath プロパティしか必要ないときのみ使えます。
他のプロパティがあるときは、
(src)
Dim g_SrcPath
If IsEmpty( g_SrcPath ) Then MsgBox "This is vbslib object file." : WScript.Quit
Dim g_Sample_vbs : get_DefineInfoObject g_Sample_vbs, g_SrcPath
'// g_Sample_vbs.FullPath
サンプル：
g_SrcPath
→ DefineInfo プロパティ (vbsool)
← ▼ ▲
get_NameDelegator
Function get_NameDelegator( Name as string, TrueName as string,
InterfaceName as string ) as InterfaceName_Delegator
指定のインターフェースを持った、正式名オブジェクトに委譲する、静的な一般名オブジェクトを取得します。
【引数】
Name
TrueName
一般名。 取得するオブジェクトの Name プロパティ
正式名。 取得するオブジェクトの委譲先 (*1)
InterfaceName
一般名オブジェクトと正式名〜が共通に持つ、インターフェースの名前 (*2)
(src)
一般名オブジェクト (*3)
返り値
(*2)
(*3)
NameDelegator インターフェース
Name と TrueName の組み合わせが初めてのときは、get_NameDelegator の内部で、
new_(InterfaceName)_Delegator 関数を呼び出して、オブジェクトを生成します。
返り値となるオブジェクトにアクセスすると、Name プロパティとオブジェクトの実体の違いを除けば、
正式名オブジェクトにアクセスします。
（ここでは一般名オブジェクト）を生成することができる、new_(InterfaceName)_Delegator
関数が定義されていること。 参考：new_X
と、(InterfaceName) インターフェースを持ったインスタンス
NameDelegator インターフェース
Class NameDelegator '// defined_as_interface
Public Name
Public Property Get TrueName() : TrueName = NameDelegator_getTrueName( Me ) : End Property
Public m_Delegate ' as ClassA or ClassB or string(before validated)
Public Property Get DefineInfo() : Set DefineInfo = m_Delegate.DefineInfo : End Property
End Class
Const F_ValidateOnlyDelegate = &h40000000
Dim g_bNeedValidateDelegate
Function NameDelegator_getTrueName( m )
Sub NameDelegator_validate( m, Flags )
Function NameDelegator_getXML( m )
DefineInfo プロパティは、オプションです。
Public Property Get DefineInfo() : Set DefineInfo = m_Delegate.DefineInfo : End Property
→ DefineInfo プロパティ
テスト
→ T_NameDelegator_vbslib フォルダ
参照
→ 名前参照、Name と TrueName が多対１の場合
場面Aの関数
Name 以外は
参照
場面Aでの Name
場面Bでの Name
ある１つのインスタンス
TrueName
（正式名）
ClassI_Delegator クラス
（一般名）
場面Bの関数
委譲
ClassI
ClassI
ClassB
ClassI
ClassA
Name = "ClassN", TrueName = "ClassA"
Name = "ClassN", TrueName = "ClassB"
一般名で選択
→ オブジェクトの Name と TrueName
参照
一般名と正式名の関係は、１対多、または、多対１があります。
(*1)
(InterfaceName) インターフェースを持った、静的な正式名オブジェクトを取得することができる
get_(TrueName) 関数が定義されていること。 参考：get_Object
get_NameDelegator 関数は、
ものです。 get_NameDelegator 関数は、get_(一般名) 関数の内部からのみ呼ばれるようにしてください。
get_Object 関数
の内部で呼ばれる get_(一般名) 関数の実装を支援する
サンプル：
Function get_GeneralObject()
Set get_GeneralObject = get_NameDelegator( "GeneralObject", "TrueName", "InterfaceName" )
End Function
Function get_TrueName() : ... : End Function
Function new_InterfaceName_Delegator() : ... : End Function
返り値となる一般名オブジェクトは、Name プロパティと委譲元となるオブジェクトの実体の違いを除けば、
同じ１つの正式名オブジェクトとして扱うことができます。 参考： 下記の図の「ある１つのインスタンス」
← ▼ ▲
new_ObjectFromStream
(src)
Sub new_ObjectFromStream( out_Obj as object, ClassName as string, Stream as variant )
ストリームから、オブジェクトを１つ生成します。
【引数】
out_Obj
ClassName
（出力） ストリームから生成した１つのオブジェクト、または Empty
生成するオブジェクトのクラス名 (下記)
Stream
XML ストリーム (下記)
ClassName 引数
XML のタグ名がクラス名に対応します。
XML のタグの中の属性まで一致するデータを元にオブジェクトを生成するときは、
XPath と同様に下記のようにします。
Set xml = LoadXML( "Sample.xml", Empty )
new_ObjectFromStream obj, "ClassA[@attr='value']", xml
参考
→ XPath の [@name='value'] （属性の値）
<Root><ClassA attr="value" ... /></Root>
VBScript コード
XMLデータ
Stream 引数
ChangeToXml
の引数に指定できるものを指定できます。
new_X に対応した関数の準備
内部で、new_X を呼び出しています。 new_X を使うのに必要な関数を用意する必要が
あります。 たとえば、ABC クラスなら、new_ABC 関数が必要です。
→ new_X
参考
テスト
→ T_ObjectFromStream フォルダ
← ▼ ▲
new_ObjectsFromStream
(src)
Sub new_ObjectsFromStream( out_Objs as array of object, ClassName as string, Stream as variant )
ストリームから、オブジェクトをいくつか生成して、配列に格納します。
【引数】
out_Objs
ClassName
（出力） ストリームから生成したオブジェクトが入った配列
生成するオブジェクトのクラス名
Stream
XML ストリーム
１つもオブジェクトを生成しなかったときでも、out_Objs には配列が格納されます。
ClassName, Stream については、
→ new_ObjectFromStream
テスト
→ T_ObjectFromStream フォルダ
← ▼ ▲
NameOnlyClass
Class NameOnlyClass
Public Name
Public Delegate
End Class
Name 変数（任意の型の識別値）と、Delegate 変数（指しているオブジェクトなど）の
対応関係を表すクラスです。
Delegate 変数を使わずに、Name だけのオブジェクトとして使うこともできます。
(src)
→ ArrayToNameOnlyClassArray
関連
→ JoinedClass
xml プロパティ
に対応しています。
← ▼ ▲
new_NameOnlyClass
Function new_NameOnlyClass( in_Name as string, in_Delegate as variant ) as NameOnlyClass
NameOnlyClass のオブジェクトを生成します。
(src)
← ▼ ▲
JoinedClass
Class JoinedClass
Public Left
Public Right
End Class
(src)
→ ArrayClass
配列番号 0 と 1 で対応関係を表すことができます
→ PointerPairClass (clib)
関連
Left 変数の値と Right 変数の値の対応関係を表すクラスです。
→ NameOnlyClass
→ pair - cpprefjp - C++ Library Reference (Web)
← ▼ ▲
new_JoinedClass
Function new_JoinedClass( Left as variant, Right as variant ) as JoinedClass
JoinedClass のオブジェクトを生成します。
【引数】
Left
Right
生成するオブジェクトの Left プロパティに設定する値
生成するオブジェクトの Right プロパティに設定する値
返り値
生成された JoinedClass のオブジェクト
ソース
→ vbslib.vbs
→ JoinedClass
← ▼ ▲
g_ObjectIDs
オブジェクトに数値の ID を割り当て、ID からオブジェクトが取得できるようにします。
Set root = new SampleRootClass
Set element = new SampleElementClass
'// Link
element.RootObjectID = root.ObjectID
Set root.Element = element
'// Call a method
element.Method
Class SampleRootClass
Public ObjectID
Public Element
Private Sub Class_Initialize()
Me.ObjectID = g_ObjectIDs.Add( Me )
End Sub
Private Sub Class_Terminate()
g_ObjectIDs.Remove Me.ObjectID
End Sub
End Class
Class SampleElementClass
Public RootObjectID
Public Sub Method()
Set root = g_ObjectIDs( Me.RootObjectID )
End Sub
End Class
サンプル
相互参照しているときの Class_Terminate
が期待通りに動作するようになります。
SampleRootClass
SampleElementClass
Element メンバー
RootObjectID メンバー （g_ObjectIDs 経由）
g_ObjectIDs
g_ObjectIDs
g_ObjectIDs
→ vbslib.vbs
ソース
.Add
.Remove
.Item
新規 ID を取得します
ID を返却します
Add できる最大数、同時に存在できる ID の数は 0x7FFE です。
同時に存在できる ID の数を超えて、Remove と Add を繰り返すと、返却された ID を再利用します。
同じオブジェクトに複数の ID が割り当てられる状況になっても、エラーにはなりません。
渡された ID に対応するオブジェクトを返します
→ ObjectSetClass
関連
← ▼ ▲
LifeGroupClass
相互参照しているオブジェクトに対して、適切に
所属オブジェクト（ルート以外）
所属オブジェクト（ルート）
LifeGroup
ハンドル（ルート以外へ） as LifeHandleClass
p
p
ハンドル（ルートへ）
→ グループのルートの生成
→ グループのメンバーの生成
DestroyReferences
ユーザーの変数
ユーザーの変数
所属オブジェクトのメンバー変数やメソッドにアクセスするときは、ハンドルのメンバー変数 p を
介する必要があります。
相互参照
関連
→ 相互参照しているときの Class_Terminate
→ ガーベージコレクション (GC)
参考
一般に、関数が終了したときにオブジェクトを参照している変数がなくなると、ガーベージコレクター
(1)
(2)
(3)
(4)
(5)
(7)
(6)
内部で相互参照するグループに LifeGroupClass を使うと下記の図のような構成になります。
グループに所属しているオブジェクトの Class_Terminate が呼び出されるタイミングは、
グループに所属しているオブジェクト（ルート オブジェクトも含む）を参照するすべてのハンドルが、
すべてのユーザーの変数から参照されなくなったときです。
( ) の中の数字は、削除される順番です。
(1) と (3)、(2) と (4)、(5) と (7) の順番は入れ替わることがあります。
(1) だけが削除されたときは、(3)が削除されるまで、(4)以降のオブジェクトは残ります。
によって
プログラム終了時に呼ばれます。 LifeGroupClass は、相互参照しているオブジェクトでも
Class_Terminate が呼び出されるようにします。
が呼ばれますが、相互参照していると Class_Terminate は呼ばれません。
Class_Terminate
このように相互参照しているオブジェクトとハンドルのオブジェクトを分けることで、
参照している変数がなくなったことをハンドルで検出できるようにしています。
オブジェクト ID を経由することで Class_Terminate を呼び出す
A
B
相互参照
→ T_Dic.vbs
T_LifeGroupClass
→ vbslib.vbs
テスト
ソース
注意
メンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要があります。
→ グループのルートの使用サンプル
辞書
のキーや配列番号で参照することで、相互参照が原因で Class_Terminate が呼ばれなく
なる状況を回避することができます。
root.p.Member
辞書のキーや配列番号
B
A
オブジェクトの Set
Class_Terminate
が呼ばれるようにします。
→ g_ObjectIDs
p を介する必要がないが、多少手間がかかるライフサイクル管理
→ DestroyerClass
→ g_ObjectIDs
← ▼ ▲
グループのルートの生成 （LifeGroupClass）
Class RootClass
Public p '// as RootBodyClass : Target object of this handle
Private Sub Class_Initialize()
Set group = new LifeGroupClass
group.AddHandle Me, new RootBodyClass
End Sub
Private Sub Class_Terminate()
If not IsEmpty( Me.p.LifeGroup.Group ) Then _
Me.p.LifeGroup.Group.AddTerminated Me.p
End Sub
End Class
使用サンプル
RootBodyClass
相互参照しているオブジェクトのグループのうち、最初に生成するオブジェクトのハンドルの
クラスは、下記のように定義します。 RootBodyClass を最初に生成するオブジェクトのクラス名
に変更すること以外は、そのままにしてください。
Class RootBodyClass
:
Public LifeGroup '// Don't write except for LifeGroupClass ■追加
Public Sub DestroyReferences() '// ■追加
Me.Reference = Empty
End Sub
End Class
最初に生成するオブジェクトのクラスは、メンバー変数 LifeGroup と、
DestroyReferences メソッド
を定義してください。
LifeHandleClass
定義サンプル
Set root = new RootClass
root.p.Member
と同じメンバーを持ちます。
<< LifeGroupClass
グループのルート（下記の RootClass）は、
RootClass
RootBodyClass
Reference
p
メンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要があります。
… p の追加が必要
相互参照しているオブジェクトを使用するコードに、この変更を要求することがどうしても
できないなら、p を介すだけのメソッドやプロパティを定義します。
DestroyReferences
LifeGroupClass
AddHandle
← ▼ ▲
グループに所属するオブジェクトの生成 （LifeGroupClass）
相互参照しているオブジェクトのグループに所属するオブジェクトのメソッドから、グループに
所属させるオブジェクトを新しく生成するときは、下記の CreateMember メソッドのように、
グループに追加します。 そうしなければ、グループが削除されるタイミングで、生成した
オブジェクトに対して DestroyReferences が呼ばれなくなります。
Class RootBodyClass
:
Public LifeGroup '// Don't write except for LifeGroupClass
Function CreateMember()
Set CreateMember = Me.LifeGroup.Group.Add( new MemberClass )
:
End Function
End Class
定義サンプル
MemberClass
Class MemberClass
:
Public LifeGroup '// Don't write except for LifeGroupClass ■追加
Public Sub DestroyReferences() '// ■追加
Me.Reference = Empty
End Sub
End Class
グループに所属するオブジェクトのクラスは、メンバー変数 LifeGroup と、
定義サンプル
DestroyReferences メソッド
を定義してください。
LifeHandleClass
です。
CreateMember メソッドの返り値は、
使用サンプル
Set root = new RootClass
Set member = root.p.CreateMember()
<< LifeGroupClass
MemberClass
Add
すぐに CreateMember の返り値を参照しなくなっても、DestroyReferences がすぐに呼ば
れることはありません。 グループに所属するすべてのオブジェクトが参照されなくなった
ときに呼び出されます。
ルートのハンドルが参照されなくなったときに、グループに所属する一部のオブジェクトが
削除されても構わないときは、ハンドルの代わりに生成したオブジェクトを返しても構いま
せん。
← ▼ ▲
グループに所属するオブジェクトの出力 （LifeGroupClass）
相互参照しているオブジェクトを出力するときは、下記の SearchMember メソッドのように、
LifeHandleClass
を生成して返してください。
Class RootBodyClass
:
Public LifeGroup '// Don't write except for LifeGroupClass
Function GetReference()
Set GetReference = Me.LifeGroup.Group.Add( Me.Reference )
End Function
End Class
定義サンプル
使用サンプル
Set root = new RootClass
Set member = root.p.GetReference()
Add (LifeGroupClass)
を呼び出し、
GetReference
ただし、グループの中で参照するときは、LifeHandleClass を生成しないでください。
そうしなければ、ルートのハンドルが削除されるタイミングで、グループに所属する一部の
オブジェクトが削除されてしまいます。 ルートのハンドルが参照されなくなったら、グループ
に所属する一部のオブジェクトが削除されても構わないときは、LifeHandleClass を生成
しなくても構いません。
← ▼ ▲
DestroyReferences メソッド
Sub （グループのに所属するオブジェクトのクラス）::DestroyReferences()
相互参照を切ります。
グループのユーザーは、本メソッドを直接呼び出さないでください。
Class_Terminate メソッド（デストラクター）が呼び出されて、オブジェクトが
破棄されるように、相互参照を切ってください。 つまり、相互に参照している
関係にあるメンバー変数に Empty や Nothing を代入してください。
<< LifeGroupClass
AddTerminated (LifeGroupClass)
から呼ばれます。
Class RootBodyClass
:
Function DestroyReferences()
Me.Member = Empty
End Function
End Class
定義サンプル
← ▼ ▲
LifeHandleClass
LifeGroupClass
（グループ）に所属する、相互参照しているオブジェクトを参照できるハンドル。
LifeHandleClass が参照している、相互参照しているオブジェクトを、グループの外にある変数
に直接格納しないでください。 もしそうしてしまうと、すべてのハンドルへの参照が無くなったときに、
相互参照が切れたオブジェクトになり、正しく動作しなくなります。
→ p
メンバー
→ Class_Terminate
生成
→ グループのルートの生成
→ グループのメンバーの生成
相互参照しているオブジェクトを参照します。
AddTerminated (LifeGroupClass)
を呼び出します。
<< LifeGroupClass
オブジェクトのメンバー変数やメソッドにアクセスするときは、メンバー変数 p を介する必要が
あります。
Set root = new RootClass
Set member = root.p.CreateMember() '// member as LifeHandleClass
member.p.Method
サンプル
←
↓