Wrapper Class around Class that uses ParamArray

Wrapper Class around Class that uses ParamArray

Post by Kevin J. Warnk » Thu, 18 Jan 2001 06:58:24



I'm trying to write a wrapper class for a Data Access component that uses
the ParamArray to accept the ADO Parameter information (like in the Fitch
and Mather example).

The sole purpose of this wrapper class is to "know" what the connection
string is, so the rest of my application doesn't need to know it.  The Data
Access component is global and services more than just one connection
string.

The problem is that when I create the wrapper method, it also uses a
ParamArray, but when I try to pass that ParamArray variable to the Data
Access component in the slot where you would think to put it, I get a type
mismatch error.

Any ideas on how to encapsulate a ParamArray argument when doing wrapper
classes?

Thanks,
- Kevin

 
 
 

Wrapper Class around Class that uses ParamArray

Post by Grinde » Thu, 18 Jan 2001 12:11:13


There's not great answer for this.  MS recommends that the called method
should check it's ParamArray for a single argument that is itself an array,
and treat it like the param array.  You probably don't have the source code
for ADODB, so you're left with something * like:

Public Sub DoSomething(ParamArray vParam() As Variant)

  Select Case Ubound(vParam) - Lbound(vParam)
  Case -1  'no parameters
    SubordinateCall
  Case 0  'one parameter
    SubordinateCall vParam(0)
  Case 1  'two parameters
    SubordinateCall vParam(0), vParam(1)
  Case 2
    ....
  End Select

End Sub

Not very slick, but viable if there's some reasonable upper limit to the
number of parameters.



Quote:> I'm trying to write a wrapper class for a Data Access component that uses
> the ParamArray to accept the ADO Parameter information (like in the Fitch
> and Mather example).

> The sole purpose of this wrapper class is to "know" what the connection
> string is, so the rest of my application doesn't need to know it.  The
Data
> Access component is global and services more than just one connection
> string.

> The problem is that when I create the wrapper method, it also uses a
> ParamArray, but when I try to pass that ParamArray variable to the Data
> Access component in the slot where you would think to put it, I get a type
> mismatch error.

> Any ideas on how to encapsulate a ParamArray argument when doing wrapper
> classes?

> Thanks,
> - Kevin


 
 
 

Wrapper Class around Class that uses ParamArray

Post by David C Hous » Thu, 18 Jan 2001 16:00:31


Try passing the parameters as an array rather than a parameter object.  Your
class can then use the IsArray function to determine if the parameter
recieved is a single parameter, or an array of parameters...

We use this all the time, and it is much faster than passing parameter
objects around...

We have thinned down our client code to eliminate connections, parameters,
and command objects.  We only use Recordsets and arrays...


> There's not great answer for this.  MS recommends that the called method
> should check it's ParamArray for a single argument that is itself an
array,
> and treat it like the param array.  You probably don't have the source
code
> for ADODB, so you're left with something * like:

> Public Sub DoSomething(ParamArray vParam() As Variant)

>   Select Case Ubound(vParam) - Lbound(vParam)
>   Case -1  'no parameters
>     SubordinateCall
>   Case 0  'one parameter
>     SubordinateCall vParam(0)
>   Case 1  'two parameters
>     SubordinateCall vParam(0), vParam(1)
>   Case 2
>     ....
>   End Select

> End Sub

> Not very slick, but viable if there's some reasonable upper limit to the
> number of parameters.



> > I'm trying to write a wrapper class for a Data Access component that
uses
> > the ParamArray to accept the ADO Parameter information (like in the
Fitch
> > and Mather example).

> > The sole purpose of this wrapper class is to "know" what the connection
> > string is, so the rest of my application doesn't need to know it.  The
> Data
> > Access component is global and services more than just one connection
> > string.

> > The problem is that when I create the wrapper method, it also uses a
> > ParamArray, but when I try to pass that ParamArray variable to the Data
> > Access component in the slot where you would think to put it, I get a
type
> > mismatch error.

> > Any ideas on how to encapsulate a ParamArray argument when doing wrapper
> > classes?

> > Thanks,
> > - Kevin

 
 
 

Wrapper Class around Class that uses ParamArray

Post by Kevin J. Warnk » Fri, 19 Jan 2001 00:11:18


The only problem I forsee with your solution is I cannot modify the Data
Access component.  It's values MUST be passed using the ParamArray argument.
Is there an easy way to use an array for the wrapper function but still use
the ParamArray on the Data Access component?

Thanks,
- Kevin



> Try passing the parameters as an array rather than a parameter object.
Your
> class can then use the IsArray function to determine if the parameter
> recieved is a single parameter, or an array of parameters...

> We use this all the time, and it is much faster than passing parameter
> objects around...

> We have thinned down our client code to eliminate connections, parameters,
> and command objects.  We only use Recordsets and arrays...



> > There's not great answer for this.  MS recommends that the called method
> > should check it's ParamArray for a single argument that is itself an
> array,
> > and treat it like the param array.  You probably don't have the source
> code
> > for ADODB, so you're left with something * like:

> > Public Sub DoSomething(ParamArray vParam() As Variant)

> >   Select Case Ubound(vParam) - Lbound(vParam)
> >   Case -1  'no parameters
> >     SubordinateCall
> >   Case 0  'one parameter
> >     SubordinateCall vParam(0)
> >   Case 1  'two parameters
> >     SubordinateCall vParam(0), vParam(1)
> >   Case 2
> >     ....
> >   End Select

> > End Sub

> > Not very slick, but viable if there's some reasonable upper limit to the
> > number of parameters.



> > > I'm trying to write a wrapper class for a Data Access component that
> uses
> > > the ParamArray to accept the ADO Parameter information (like in the
> Fitch
> > > and Mather example).

> > > The sole purpose of this wrapper class is to "know" what the
connection
> > > string is, so the rest of my application doesn't need to know it.  The
> > Data
> > > Access component is global and services more than just one connection
> > > string.

> > > The problem is that when I create the wrapper method, it also uses a
> > > ParamArray, but when I try to pass that ParamArray variable to the
Data
> > > Access component in the slot where you would think to put it, I get a
> type
> > > mismatch error.

> > > Any ideas on how to encapsulate a ParamArray argument when doing
wrapper
> > > classes?

> > > Thanks,
> > > - Kevin

 
 
 

Wrapper Class around Class that uses ParamArray

Post by Matthew Curlan » Fri, 19 Jan 2001 03:19:44


The only way to do this is to step slightly outside what VB can do natively.
By far the easiest way to do this is with tools and code from my book. This
is a 10 minute exercise if you have the book (less if you've done it
before). You need to do the following:

1) Define a second version of the interface you're calling that looks the
same as the first but doesn't have the vararg attribute on the method in
question (strangely enough, the ParamArray effect is created via a function,
not a parameter, level attribute). To do this with the 'PowerVB Type Library
Editor' add-in, create a new type library, then use the Internalize Types/As
Proxy/Single Type command to copy the interface you want, then open the
context menu for the method(s) in question and select 'Remove ParamArray'.
You can rename the type if you like, or just plan to qualify it with the
library name. Saving the typelib will add it to your project. Note that the
'As Proxy' is important here to avoid corrupting the registry (see pages
404-408).

2) Get the ParamArray parameter into a normal VB array variable so you can
pass it to the modified version of your interface. The book shows how to do
this using DerefEBP on pages 251-253, and a second technique is shown in the
PowerVB\Code\CallDispatch.bas file. The first technique reads the data
directly off the stack (the downside here is that you get different values
in pcode/native for module functions, but this shouldn't have any effect if
you're doing this in a class module, where the first parameter is always
offset 12 bytes from EBP), the second uses the VarPtr of another variable
(ByVal, not array/string/object type) to get the address of the ParamArray.

Using the support code from the book, the whole thing looks something like
this:
Public Sub CallMe(ParamArray Args() As Variant)
Dim ArgsLocal() As Variant
Dim pFooModified As IFooModified 'Modified interface
    VBoost.AssignSwap ByVal VarPtrArray(ArgsLocal), ByVal DerefEBP.Call(12)
    VBoost.AssignAddRef pFooModified, m_pFoo 'Set does an unneeded QI, this
will just AddRef.
    pFooModified.CallMe ArgsLocal
End Sub

Note that you have to be very careful using stolen ParamArrays in VB because
they may contain VT_BYREF Variants. VB does not handle VT_BYREF variants in
local/module level variables, or in any Variant array except for ParamArrays
(hence the tight restrictions on passing paramarrays). Therefore, if you
want to do anything with the ArgsLocal array besides passing to another
function that handles a ParamArray, you need to read and write elements in
the array by passing them as ByRef arguments to another function. If you
don't do this, any ByRef-ness of the Variants will be lost, and you might
have other problems as well. The best thing to do with a stolen ParamArray
is to pass as described here to another function that expects the
ParamArray.
-Matt
http://www.PowerVB.com

 
 
 

1. Visual C++ ADO- linking to wrapper classes gives link errror but not raw classes

Hi all,

I am using the #import directive to bring in the ADO typelib info into my
ATL project. If I try to use one of the wrapper classes that return values
and use the com-error object the project does not link. If I use the raw
classes that return Hresults the project compiles. What am I missing?

Thanks
Mark

2. shared time dimension

3. Using class objects as a wrapper for DAO

4. help on security mechanisms

5. Using Class Builder Utility to create a base class (VB6)

6. Upgrade from Version 6 to 8: help needed urgently!

7. Passing Classes to other classes (using user defined types)

8. Screen Re-sizing

9. Good C++ Class Wrapper for ODBC??

10. PyGreSQL, suggestion for DB wrapper class

11. Any Good C++ Wrapper Classes