Visual Basic Concepts

Global Objects and Code Libraries

See Also

You can build libraries of general-purpose procedures in Visual Basic by making the procedures methods of a class module. Set the Instancing property of the class module to any value except Private or PublicNotCreatable, so that clients can create instances of the class.

When you choose the value GlobalMultiUse for the Instancing property of a class, and then make the project, you can subsequently use the properties and methods of the class without having to explicitly create an instance of the class.

Properties and methods of a GlobalMultiUse object (or global object) are added to the global name space of any project that uses the object. That is, in another project you can set a reference to the component, and the names of the global object’s properties and methods will be recognized globally, just as if they were part of Visual Basic.

Important   The properties and methods of a global object only become part of the global name space when the component is referenced from other projects. Within the project where you created the GlobalMultiUse class module, objects created from the class are just ordinary objects.

The following code fragments show the difference between using MultiUse and GlobalMultiUse objects. Both assume that you’ve used the References dialog box to set a reference to a component that provides a Financials object whose methods are general-purpose financial functions.

Code required to use a MultiUse Financials object:

' This code goes in a standard module.
' Declare a global variable to contain the instance.
Public gfins As New Financials

' This code goes in a form that uses a method of the
'   Financials object.
Private Sub cmdCalculateResult_Click()
   txtResult.Text = gfins.LeastReasonableReturn( _
      CCur(txtBeginningBalance.Text))
End Sub

Note   When you use the code above, the Financials object is created the first time the variable gfins is used in code. This incurs a slight increase in overhead on each function call. You can avoid this by explicitly creating the Financials object in Sub Main (for standalone executables) or on first object creation (for components).

By contrast, the code to use a GlobalMultiUse Financials object requires no global variable:

Private Sub cmdCalculateResult_Click()
   txtResult.Text = LeastReasonableReturn( _
      CCur(txtBeginningBalance.Text))
End Sub

Visual Basic creates a hidden instance of the Financials class the first time a line of code containing one of its methods is executed.

Note   As explained later in this topic, the hidden instance incurs the same slight overhead per call as declaring gfins As New in the previous code example.

In the Object Browser, procedures that are part of a project’s global name space are displayed in the <globals> entry in the Classes list. Figure 8.1 shows this for a project group that uses the Financials class.

Figure 8.1   Methods of a GlobalMultiUse class appear in <globals>

The Object Browser displays the names of classes and members defined in your projects in bold type.

Tip   You can move directly to the code that defines classes and members by double-clicking names displayed in bold type.

Components That Use Global Objects Internally

Setting the Instancing property of a class to GlobalMultiUse or GlobalSingleUse allows client programs to use the properties and methods of the class as if they were global functions, but within the project where you defined the GlobalMultiUse class module, objects created from the class are not global.

For example, suppose your MyUtilities project contains a Utilities class whose Instancing property is set to GlobalMultiUse, and that the class has an InvertMatrix method. Any client project that has a reference to MyUtilities can call InvertMatix as if it were a global function. However, within the MyUtilities project, you cannot use InvertMatrix as if it were a global function.

If you want to use a global instance of the Utilities class within the MyUtilities project, you can add the following declaration to a standard module in MyUtilities:

Public Utilities As New Utilities

Thereafter, whenever you need to use InvertMatrix (or any other procedure supplied by the Utilities class), you can qualify it with the class name:

   Utilities.InvertMatrix aintMyLargeMatrix

The first time you use a method of the Utilities class in this fashion, an instance of the class is created automatically, because the global variable is declared As New. Using the class name as the name of the variable makes it clear which of the modules within your component is supplying the procedure.

Note   You must declare the global variable in a standard module, not a class module, in order for this technique to work.

Creating Object Properties for Global Objects

Visual Basic has properties of its <globals> that are themselves objects — for example, the App object and the Printers collection. You can create similar object properties for your own global classes.

Suppose you’ve created a Registry class for accessing the Windows registry, and that you have a Globals class whose Instancing property is GlobalMultiUse. The following code fragment shows how you can add a Registry property to your Globals class:

Private mRegistry As Registry

Private Sub Class_Initialize()
   Set mRegistry = New Registry
End Sub

Public Property Get Registry() As Registry
   Set Registry = mRegistry
End Sub

Once you’ve compiled your component, you can reference it from other projects. If the Registry class includes a FindKeyContaining method, you might write code like this to use it:

Private Sub Command1_Click()
   lblResult.Caption = _
      Registry.FindKeyContaining(txtInput.Text)
End Sub

This code assumes that the form contains a text box in which the user enters a string to be located (txtInput), and a label in which the registry key is displayed (lblResult). Notice that you didn’t have to create an instance of Globals before using the Registry object.

Tip   Always use Property Get when you add an object property to your global object. If you use a public variable instead, you can accidentally destroy the object the property provides by setting the property to Nothing.

Guidelines for Using Global Objects

You may find the following useful in getting the most out of global objects:

Important   Each client that uses the properties and methods of a GlobalMultiUse class gets its own instance of the class. In other words, the "Global" in GlobalMultiUse does not mean "one global instance that all clients share."

Limitations of GlobalMultiUse Objects

When you’re deciding whether to use a global object or explicitly declare a variable to hold an instance of an object, the following may be of use:

GlobalSingleUse Objects

For out-of-process components only, you can set the Instancing property of a class module to GlobalSingleUse. If you do this, a separate instance of your component will be loaded into memory for each client. This requires a lot more memory than providing GlobalMultiUse objects.

If you simply want each client to have a separate thread of execution for your global procedures, consider using GlobalMultiUse for your global objects and making your out-of-process component multithreaded, as described in "Scalability and Multithreading."

Note   GlobalSingleUse is not allowed in ActiveX DLL projects, because multiple instances of a DLL cannot be loaded into a clients process space.

For More Information   See "Scalability Through Multiple Processes: SingleUse Objects."