2.6 IDispatch

only for RuBoard - do not distribute or recompile

2.6 IDispatch

As mentioned previously, _Animal is directly derived from an interface called IDispatch . Interfaces derived from IDispatch often have the [dual] attribute and appropriately are called dual interfaces . This is because the interface supports vtable binding (binding at compile time) and late binding (binding at run-time). The methods that comprise IDispatch facilitate the process known as late binding, which results from code like that shown in Example 2.6.

Example 2.6. Late Binding
 'Late binding Cow Dim cow1 As Object Set cow1 = CreateObject("Animals.Cow")  MsgBox cow1.Noise 

CreateObject uses the ProgID for the component and maps it to a CLSID. This allows an instance of the component to be created. Internally, this is done by calling the CoCreateInstanceEx API. Once the component is loaded, a call to QueryInterface is made and a pointer to an IDispatch interface is returned. The generic Object datatype really means IDispatch . Then late binding is used to make the call to the Noise method.

Late binding is generally avoided whenever possible for reasons of efficiency (it's extremely slow). But in scripting languages like VBScript and JavaScript, late binding is the only choice available. This is because type information is used at compile time to bind method calls to the object. Code run in a scripting environment is not compiled. It is interpreted at runtime, line by line. Therefore, there needs to be a mechanism for calling the methods of an object in environments such as these. This is where IDispatch comes in. The four methods of IDispatch are:

  • GetTypeInfoCount

  • GetTypeInfo

  • GetIDsOfNames

  • Invoke

2.6.1 GetTypeInfoCount

GetTypeInfoCount returns either a or a 1, depending on the availability of type information. Since we know the Animals component contains type information, an implementation of GetTypeInfoCount written in Visual Basic might be as simple as this:

 Private Sub GetTypeInfoCount(  ) As Long GetTypeInfoCount = 1 End Sub 

2.6.2 GetTypeInfo

GetTypeInfo returns an ITypeInfo interface pointer, which provides the means for accessing information in a type library. ITypeInfo is useful when no prior knowledge of a component is available. Utilities such as Object Browser and OLE View use IDispatch::GetTypeInfo to get information about a component from a type library. Typically, you are familiar with the components you use in your day to day development efforts. Therefore, this method is rarely used.

2.6.3 GetIDsOfNames

Refer back to the _Animal interface for a moment and look at the [id] attribute that accompanies each method in the interface. This ID is called a dispatch identifier , or DISPID. This is the value that is returned by GetIDsOfNames . Without going into detail, GetIDsOfNames basically takes the method name (like Noise ) as an argument and returns the DISPID associated with that method. It is this number that is used in place of the function name to make a method invocation at runtime. This is for efficiency reasons. Remember, some COM components are out-of-process servers that might be running on another machine. Passing an integer across a network is more efficient than passing a string.

2.6.4 Invoke

Invoke is the heart of the IDispatch interface. This method is responsible for making the late binding call to a method or property. Invoke indirectly calls a method or property using the DISPID returned by GetIDsOfNames . The return value, if there is one, is packed into a VARIANT structure and returned to the caller.

Now that we have discussed IUnknown and IDispatch , you should have a better idea of what is going on internally in a component written in Visual Basic. We now know that there is a little more going on in the _Animal interface than was initially apparent. Figure 2.6 shows a graphic depiction of the _Animal interface.

Figure 2.6. Animal interface

And with this last piece of information, the question "Why can't we use VB to generate the interfaces we need?" can finally be answered . The answer is very simple. We can't use VB because the interfaces we will need must be derived directly from IUnknown . How do we know that they must be derived directly from IUnknown ? Because that's what the Platform SDK says they are derived from. Remember, we have contracts to abide by here!

only for RuBoard - do not distribute or recompile

Visual Basic Shell Programming
Visual Basic Shell Programming
ISBN: B00007FY99
Year: 2000
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net