重拾VB6(16):Object Model, Collection Class, and ActiveX Designer

来自MSDN-2001-OCT: Visual Tools and Languages/Visual Studio 6.0 Documentation/Visual Basic Documentation/Using Visual Basic/Programmer’s Guide/Part 2: What Can You Do With Visual Basic/Programming with Objects/Object Models

 

1. How to keep track of all object references

(1) According to COM rules, the only information you can depend on is whether or not the reference count is zero. You know when the reference count reaches zero, because your object's Terminate event occurs.

To make using objects more efficient, the Component Object Model (COM) specifies a number of complex shortcuts to its reference counting rules. The net result is that you couldn't trust the value of the reference count even if you had access to it.

(2) Declare your object variables as class types, instead of As Object.

(3) For collections of object references, don't use the Visual Basic Collection object by itself.

(4) Organize your object into a hierarchy, so that it's easy to walk through the whole model and reports on all the existing objects.

(5) Don't declare variables As New, because if you use one after you've set it to Nothing, Visual Basic obligingly creates another object.

(6) Circular references are the most difficult kind to shut down cleanly.

 

2. Object Models

(1) 可以用成员对象的办法来express对象之间的hierarchy。比如:

' Code for the Declarations section of the
' SmallBusiness class module.
Public Name As String
Public Product As New Product
Public Employees As New Collection
Public Customers As New Collection

Object properties work well when the relationship between objects is one-to-one. It frequently happens, however, that an object of one type contains a number of objects of another type. 这时候我们就要用collection。

(2) Class Builder creates robust object properties and collection classes, and allows you to rearrange your model easily.

(3) Tip   When you assign a Parent property to an object in a collection, don't use a reference to the Collection object. The real parent of the object is the object that contains the collection. If the Parent property points to the collection, you'll have to use two levels of indirection to get to the real parent — that is, obj.Parent.Parent instead of obj.Parent.

(4) One of the biggest problems with Parent properties is that they create circular references. 解决的办法是给父亲object设计一个teardown方法,先把它的所有孩子都set nothing,然后再set它自己nothing.

When a Collection object is destroyed, Visual Basic sets all the object references it was holding to Nothing.

If there are variables anywhere in your program that still contain references to the SmallBusiness object, or to any of the objects it contains, those objects won't be destroyed. Part of the cleanup for your program must be to ensure that all object variables everywhere are set to Nothing.

To test whether this is happening, you may want to add some debugging code to your objects. For example, you can add the following code to a standard module:

VB.net语言: Dim frm As New Form1
' Global debug collection
Public gcolDebug As New Collection

' Global function to give each object a unique ID.
Public Function DebugSerial() As Long
   Static lngSerial As Long
   lngSerial = lngSerial + 1
   DebugSerial = lngSerial
End Function

In each class module, you can put code similar to the following. Each class provides its own name where "Product" appears.

' Storage for the debug ID.
Private mlngDebugID As Long

Property Get DebugID() As Long
   DebugID = mlngDebugID
End Property

Private Sub Class_Initialize()
   mlngDebugID = DebugSerial
   ' Add a string entry to the global collection.
   gcolDebug . Add "Product Initialize; DebugID=" _
   & DebugID , CStr( DebugID)
End Sub

Private Sub Class_Terminate()
   ' Remove the string entry, so you know the object
   ' isn't around any more.
   gcolDebug . Remove CStr( DebugID)
End Sub

At any time, you iterate over the global collection to see what objects haven't been destroyed.

 

3. Creating Your Own Collection Classes

(1) The ID property is the key for retrieving or deleting an Employee object from the collection, so it must be set once and never changed. This is accomplished with a Static Boolean variable that is set to True the first time the property is set. The property can always be read, because there is a Property Get.

Option Explicit
' Properties of the Employee class.
Public Name As String
Public Salary As Long  

' Private data for the write-once ID property.
Private mstrID As String

Property Get ID() As String
   ID = mstrID
End Property

' The first time the ID property is set, the static
' Boolean is also set.  Subsequent calls do nothing.
' (It would be better to raise an error, instead.)
Property Let ID( strNew As String)
   Static blnAlreadySet As Boolean
   If Not blnAlreadySet Then
      blnAlreadySet = True
      mstrID = strNew
   End If
End Property

(2) There are three general approaches you can take to implementing object containment using collections.

a) Public Collection: In the SmallBusiness class module, declare an Employees variable As Collection, and make it Public. This is the cheap solution.

The Collection object's very flexibility betrays it — you can put anything into a Collection, including the KitchenSink object.

b) Private Collection: In the SmallBusiness class module, declare an mcolEmployees variable As Collection, and make it Private. Give the SmallBusiness object a set of methods for adding and deleting objects. This is the least object-oriented of the three designs.

You can gain some robustness by making the Collection object private, but you lose the ability to use For Each … Next with the collection.

c) Implement your own collection class, by creating a collection class module named Employees, as described later in this chapter. Give the SmallBusiness object a read-only property of the Employees class.

Creating your own collection class: gives you the robustness of encapsulation, and as a bonus you get back the ability to use For Each … Next.

(3) Important   In order for your collection classes to work with For Each … Next, you must provide a hidden NewEnum method with the correct procedure ID.

' NewEnum must return the IUnknown interface of a
' collection's enumerator.
Public Function NewEnum() As IUnknown
   Set NewEnum = mcolEmployees . [ _NewEnum ]
End Function

The important thing you're delegating to the Collection object is its enumerator. An enumerator is a small object that knows how to iterate through the items in a collection.

The square brackets around the Collection object's _NewEnum method are necessary because of the leading underscore in the method name. This leading underscore is a convention indicating that the method is hidden in the type library.

You can't name your method _NewEnum, but you can hide it in the type library and give it the procedure ID(-4) that For Each … Next requires.

(4) Steps to Implement a Collection Class:

a) Add a class module to your project, and give it a name — usually the plural of the name of the object the collection class will contain.

b) Add a private variable to contain a reference to the Collection object your properties and methods will delegate to.

c) In the Class_Initialize event procedure, create the Collection object.

d) Add a Count property and Add, Item, and Remove methods to your class module; in each case, delegate to the private Collection by calling its corresponding member.

e) When you implement the Add method, you can override the behavior of the Collection object's undiscriminating Add method by accepting only objects of one type.

f) Use the Procedure Attributes dialog box to make the Item method the default for your collection class.

g) Add a NewEnum method, as shown below. Use the Procedure Attributes dialog box to mark it as hidden, and to give it a Procedure ID of –4 so that it will work with For Each … Next.    

Public Function NewEnum() As IUnknown
   Set NewEnum = mcol . [ _NewEnum ]
End Function 

Note   The code above assumes that the private variable in step 2 is named mcol.

h) Add custom properties, methods, and events to the collection class.

Note   The Class Builder utility, included in the Professional and Enterprise editions of Visual Basic, will create collection classes for you. You can customize the resulting source code.

4. ActiveX Designers

(1) A designer provides a visual design window in the Visual Basic development environment. You can use this window to design new classes visually.

Objects created from the classes you design in this fashion have separate design-time and run-time behavior and appearance, although many objects — such as forms and controls — look very similar in the two modes.

(2) Difference between ActiveX Designer Classes to ActiveX controls:

  • If an object created from an ActiveX designer class is visible at run time, it has its own window. It is not contained within another form, as ActiveX controls are.
  • Like form classes, but unlike ActiveX controls, the classes produced by ActiveX designers are private classes. You cannot declare public methods that use these classes as argument types or return types.
  • Public Function A() As UseConnection1       'Error
    Public Sub B( CallBack As UseConnection1)    'Error

    (3) Creating ActiveX Designers: You can use the ActiveX Designer Software Development Kit to create new ActiveX designers for use with Visual Basic.

    Note   The ActiveX Designer SDK requires a C++ compiler, such as Microsoft Visual C++. ActiveX designers cannot be written using Visual Basic.

    (4) Adding an ActiveX Designer to the Project Menu: Project->Components->Designers

    (5) Like all designers, the Microsoft Forms designer has its own run-time .dll. Using this designer in a Visual Basic project will therefore increase the memory requirements of the resulting executable.

    (6) Inserting a New Instance of an ActiveX Designer: On the Project menu, click Add designer (where designer is the name of the designer) to display a list of installed designers. Pick the designer you want from the list.

    (7) ActiveX Designers and SourceCode Control: When attempting to edit a file created by a designer, you may not be prompted to check out the file before editing. Additionally, some designers write files out to the file system; SourceCode control may not be aware of these files.

     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值