Visual Basic Concepts
Instancing for Classes Provided by ActiveX Components
The value of the Instancing property determines whether your class is private — that is, for use only within your component — or available for other applications to use.
As its name suggests, the Instancing property also determines how other applications create instances of the class. The property values have the following meanings.
Private means that other applications aren’t allowed access to type library information about the class, and cannot create instances of it. Private objects are only for use within your component.
PublicNotCreatable means that other applications can use objects of this class only if your component creates the objects first. Other applications cannot use the CreateObject function or the New operator to create objects from the class.
MultiUse allows other applications to create objects from the class. One instance of your component can provide any number of objects created in this fashion.
An out-of-process component can supply multiple objects to multiple clients; an in-process component can supply multiple objects to the client and to any other components in its process.
GlobalMultiUse is like MultiUse, with one addition: properties and methods of the class can be invoked as if they were simply global functions. It’s not necessary to explicitly create an instance of the class first, because one will automatically be created.
SingleUse allows other applications to create objects from the class, but every object of this class that a client creates starts a new instance of your component. Not allowed in ActiveX DLL projects.
GlobalSingleUse is like SingleUse, except that properties and methods of the class can be invoked as if they were simply global functions. Not allowed in ActiveX DLL projects.
Class Modules and Project Types
The value of the Instancing property is restricted in certain project types. Allowed values are shown in the following table:
|Instancing Value||ActiveX EXE||ActiveX DLL||ActiveX Control|
Dependent Objects (PublicNotCreatable)
The value of the Instancing property determines the part an object plays in your component’s object model, as discussed in "Organizing Objects: The Object Model."
If the Instancing property of a class is PublicNotCreatable, objects of that class are called dependent objects. Dependent objects are typically parts of more complex objects.
For example, you might allow a client application to create multiple Library objects, but you might want Book objects to exist only as parts of a Library. You can make the Book class PublicNotCreatable, and let the user add new books to a Library object by giving the Library class a Books collection with an Add method that creates new books only within the collection.
Your component can support as many dependent objects as necessary. You can write code in the Add method of a collection class to limit the number of objects in the collection, or you can allow the number to be limited by available memory.
*For More Information* Dependent objects are discussed in detail in "Dependent Objects," later in this chapter.
Externally Creatable Objects
All values of the Instancing property besides PublicNotCreatable and Private define externally creatable objects — that is, objects that clients can create using the New operator or the CreateObject function.
MultiUse vs. SingleUse
In ActiveX DLLs, Instancing for an externally creatable class will most commonly be MultiUse. This setting allows an in-process component to supply any number of instances of the class to the client executable, and to any other in-process component.
For ActiveX EXEs, the Instancing values SingleUse and MultiUse define very different behaviors for a class. MultiUse makes the most efficient use of memory, because it allows one instance of your component to provide multiple objects to multiple client applications without duplication of resources or global data.
For example, suppose the SmallMechanicals component provides a Widget class, and the Instancing property of the class is set to MultiUse. If one client application creates two Widget objects, or if two client applications each create a Widget object, all the Widgets will be supplied from one instance of your component.
If the Instancing property of the Widget class is set to SingleUse, the result of both scenarios above is that a separate copy of your component will be loaded into memory for each Widget created. The uses and limitations of this behavior are discussed in "Building Code Components," and in "ActiveX Component Standards and Guidelines."
MultiUse and Multithreading
If your component is an ActiveX EXE marked for unattended execution (that is, it has no user interaction whatever), and the Instancing property of the Widget class is set to MultiUse, the result of both scenarios above is that two Widget objects are created in same copy of SmallMechanicals, each on its own thread of execution.
Apartment Model threading is used, meaning that each thread is like an apartment, and objects in different apartments are unaware of each other’s existence. This is accomplished by giving each Widget its own copy of the SmallMechanicals component’s global data.
*For More Information* The use of multithreading or SingleUse instancing to avoid blocked execution is discussed in "Building Code Components."
Frequently it’s useful to have utility functions that users of your component can employ without first creating an instance of one of your objects. In out-of-process components, such functions are frequently implemented as properties or methods of the Application object.
If the Instancing property for a class is marked GlobalMultiUse or GlobalSingleUse, then properties and methods of the class can be invoked without explicitly creating an instance of the object.
For example, suppose you want your SmallMechanicals component to provide a GlobalUtility object whose methods are general-purpose functions. You can add a class module to the SmallMechanicals project, set the Name property to GlobalUtility, and set the Instancing property to GlobalMultiUse.
Now you can add properties and methods to the class module. For example, you might implement a ReversePolarity method and a read-only WidgetCount property:
Public Sub ReversePolarity() ' (Code to reverse polarity on all Widgets.) End Sub
In the client application, the ReversePolarity method can be invoked without first creating a GlobalUtility object:
Private Sub Command1_Click() ' No object variable is required. ReversePolarity End Sub
*Note* The properties and methods of a GlobalMultiUse object are not part of the global name space of the component that provides the object. For example, within a project that contains the GlobalUtility class, you must explicitly create an instance of GlobalUtility in order to use the object's properties and methods. Other limitations of global objects are listed in "Global Objects and Code Libraries," in "Building Code Components."
Be careful when choosing names for the properties and methods of global objects. Using common or obvious names may result in name collisions with other components. Name conflicts must be resolved by qualifying the property or method with the type library name:
Private Sub Command1_Click() SmallMechanicals.ReversePolarity Esalen.ReversePolarity End Sub
*Important* The "global" in global objects refers to the fact that all of the object’s properties and methods are available in the global name space of your project. It does not mean that one object is automatically shared by all clients. Each client that uses your component gets its own global object.
*For More Information* "Providing Named Constants for Your Component," later in this chapter, discusses the use of global objects to provide string constants and non-integer constants. Code components are discussed in depth in "Building Code Components."