PDA

Click to See Complete Forum and Search --> : Implementing Interfaces from TLBs


psyang
Mar 21st, 2001, 10:30 AM
I am working on a project where interfaces are defined in TLBs via IDL, and are implemented in VB using Implements.

Since VB can only implement interfaces derived from IUnknown, it was decided that every interface support a standard set of properties which can be queried by a central error object. Things like the interface name can then be retreived regardless of what interface was passed in - polymorphism!

The error object takes, as a parameter, a reference to the interface. Since this interface can be anything, the type of the parameter is Object.

Unfortunately, when an interface is passed in, the type changes to the implementing class' default interface. As an example:

Class 1
-------
Implements Class2

Property Get Interface() as String
Interface = "Class1"
End Property

Property Get Class2_Interface() as String
Class2_Interface = "Class2"
End Property

Error Object
------------
Public Sub PushError( objInterface as Object )

MsgBox "Error in " & objInterface.Interface

End Sub

Main Tester
-----------
Sub Main()

dim objClass1 as Class1
dim objClass2 as Class2
dim objError as ErrorObject

set objError = new ErrorObject
set objClass1 = New Class1

objError.PushError( objClass1 ) ' Displays "Class1"

set objClass2 = objClass2
objError.PushError( objClass2 ) ' Displays "Class1", not "Class2"

End Sub

What bugs me is that if the interfaces for Class1 and Class2 are defined in VB (ie. a "dummy class" is created with just the interface and no implementation), this works fine. When the interfaces come from a TLB, however, PushError always reports Class1 in my above example.

As well, in the Watch Window, when the class definition is done in VB, objInterface is correctly reported as Object/Class1 or Object/Class2. When the class definition is done in TLBs, objInterface is always reported as Object/Class1.

Any ideas?

-Peter

tumblingdown
Mar 21st, 2001, 10:36 AM
Can we have a look at the idl?


td.

psyang
Mar 21st, 2001, 11:42 AM
Here's the IDL for the error object (the PushError method receives the interface pointer in SourceError):

[ uuid(4BEA1AB1-F91D-11d4-951D-00D0B7436105),
oleautomation
]
interface IDMSError : IUnknown {
[helpstring("Push an error onto the stack")]
HRESULT _stdcall PushError( [in] long ErrorNumber,
[in] IDispatch *ErrorSource,
[in] BSTR ErrorProcedure,
[in] long ErrorLine,
[in, optional] VARIANT ErrorMessage );

[helpstring("Pop an error from the stack")]
HRESULT _stdcall PopError( [in,out] long *ErrorNumber,
[in,out] BSTR *ErrorHeader,
[in,out] BSTR *ErrorMessage,
[out,retval] VARIANT_BOOL *StackNotEmpty);
[helpstring("Clear error stack")]
HRESULT _stdcall Clear( );

[helpstring("Notify top-level error handler")]
HRESULT _stdcall Notify();

[propget, helpstring("Gets Interface Name")]
HRESULT _stdcall InterfaceName( [out,retval] BSTR *InterfaceName );

};

Here's a typical interface that might be passed in:

[ uuid(620DBD22-FEA0-11d4-9522-00D0B7436105),
oleautomation
]
interface IDMSBase : IUnknown {
[propputref, helpstring("Set error object")]
HRESULT _stdcall ErrorObject( [in] IDMSError *ErrorObject );

[propget, helpstring("Class name")]
HRESULT _stdcall ClassName( [out, retval] BSTR *ClassName );

[propget, helpstring("Gets Interface Name")]
HRESULT _stdcall InterfaceName( [out,retval] BSTR *InterfaceName );

};