NewEnum in Interface 
Author Message
 NewEnum in Interface

Hi

I was wondering if there is any way of specifying the NewEnum enumerator
mechanism in a VB6 interface class and then delegating to the  iterator
implemented by the underlying implementing collection class (without
having to use the IEnumVariant approach) ? I was hoping(!) for a more
simple delegation solution.

Alternatively, perhaps there is a simple way to implement any of the
following

Dim l_cCollection as ICollection
Dim l_oObject as Object

a) For each l_oObject in l_cCollection
(effectively what I am asking above)

or alternatively, something like

b) For each l_oObject in l_cCollection.Iterator
c) For each l_oObject in GetIterator(l_cCollection)

Thx

Simon



Fri, 04 Nov 2011 17:15:31 GMT  
 NewEnum in Interface



Quote:
> I was wondering if there is any way of specifying the
> NewEnum enumerator mechanism in a VB6 interface
> class and then delegating to the  iterator implemented
> by the underlying implementing collection class (without
> having to use the IEnumVariant approach) ? I was
> hoping(!) for a more simple delegation solution.

AFAIK, you can specify only one procedure
in your (implementing) container-class with the (-4)-
Attribute, which then acts as the entrypoint for an
enumeration.

If such a Container-Class needs to support more
Enumeration-entrypoints than the one on the default-
interface, you could enhance your Interface-Class
about a concrete Enumeration-Delegation-procedure
(e.g. named 'Iterator') and not only Implement the
Interface then in your other container-class, but
also create a hidden instance of your ICollection-
Interface-Class.

In the following example I've named this additional
container-interface IOtherItems and not ICollection,
but you should get the idea...

'------------------Into a Class IOtherItems----------------
Option Explicit

Private mCol As Collection

Private Sub Class_Initialize()
  Set mCol = New Collection
End Sub

'a helper, to hand out the internal Collection to the implementing Class
Friend Function GetCol() As Collection
  Set GetCol = mCol
End Function

'**********now the publically visible Interface-Def************
'...
'ensure, you've set Proc-Attr to -4 for this function
Public Function Iterator() As IUnknown
  Set Iterator = mCol.[_NewEnum]
End Function

'this is the rest of our interface, only with virtual Defs
Public Sub Add(Item, Key)
End Sub
Public Sub Remove(Key)
End Sub
Public Property Get Item(Key) As cOtherItem
End Property

'------------------Into a Class cOtherItem----------------
Option Explicit

Public SomeLongInt As Long
Public SomeString As String

'------------------Into a Class cItem----------------
Option Explicit

Public SomeLongInt As Long
Public SomeString As String

'------------------Into a Class cItems----------------
Option Explicit

Private mCol As Collection 'for the normal cItem-Types

Implements IOtherItems 'the Interface we want to implement...
Private mIOtherItems As IOtherItems 'but we create an instance here also

Private Sub Class_Initialize()
  Set mCol = New Collection 'for the normal cItem-Types
  Set mIOtherItems = New IOtherItems
End Sub

'*******everything in this block is for the normal cItem-Types******
Public Sub Add(Item, Key)
  mCol.Add Item, Key
End Sub

Public Sub Remove(Key)
  mCol.Remove Key
End Sub

Public Property Get Item(Key) As cItem
  Set Item = mCol(Key)
End Property

'set Proc-Attr to -4 (and also "hidden", if you want that)
Public Function Iterator() As IUnknown
  Set Iterator = mCol.[_NewEnum]
End Function
'************end of the normal cItem-Types code-block************

'*****and now the code-block for the IOthers-Implementation******
Private Sub IOtherItems_Add(Item As Variant, Key As Variant)
  mIOtherItems.GetCol.Add Item, Key
End Sub

Private Property Get IOtherItems_Item(Key As Variant) As cOtherItem
  Set IOtherItems_Item = mIOtherItems.GetCol(Key)
End Property

Private Function IOtherItems_Iterator() As stdole.IUnknown
  Set IOtherItems_Iterator = mIOtherItems.Iterator
End Function

Private Sub IOtherItems_Remove(Key As Variant)
  mIOtherItems.GetCol.Remove Key
End Sub

'------------------Into a Form for testing----------------
Option Explicit

Private Sub Form_Load()
Dim i As Long
Dim Items As cItems
  Set Items = New cItems 'instantiation against the Default-interface

  'now we add some normal items into this container-instance
  Dim NewItem As cItem
  For i = 1 To 3
    Set NewItem = New cItem
    NewItem.SomeLongInt = i
    NewItem.SomeString = "cItem" & i
    Items.Add NewItem, "Key" & i
  Next i

  'now we only cast the container-instance against IOtherItems-interface
  Dim OtherItems As IOtherItems
  Set OtherItems = Items 'as said, we do only a cast here

  'and add some cOtherItem(s) against this second container-interface
  Dim NewOtherItem As cOtherItem
  For i = 1 To 3
    Set NewOtherItem = New cOtherItem
    NewOtherItem.SomeLongInt = i
    NewOtherItem.SomeString = "cOtherItem" & i
    OtherItems.Add NewOtherItem, "Key" & i
  Next i

  'finally we should be able, to enumerate on
  'both interfaces (of the same container-instance)
  Dim Item As cItem
  For Each Item In Items
    Debug.Print Item.SomeString
  Next Item

  Debug.Print

  'and the other items in that container (over the second interface)
  Dim OtherItem As cOtherItem
  For Each OtherItem In OtherItems
    Debug.Print OtherItem.SomeString
  Next OtherItem
End Sub

HTH,

Olaf



Fri, 04 Nov 2011 23:28:37 GMT  
 NewEnum in Interface
I need to digest this  a bit ... but thanks very much, Olaf

Simon

Quote:



>> I was wondering if there is any way of specifying the
>> NewEnum enumerator mechanism in a VB6 interface
>> class and then delegating to the  iterator implemented
>> by the underlying implementing collection class (without
>> having to use the IEnumVariant approach) ? I was
>> hoping(!) for a more simple delegation solution.

> AFAIK, you can specify only one procedure
> in your (implementing) container-class with the (-4)-
> Attribute, which then acts as the entrypoint for an
> enumeration.

> If such a Container-Class needs to support more
> Enumeration-entrypoints than the one on the default-
> interface, you could enhance your Interface-Class
> about a concrete Enumeration-Delegation-procedure
> (e.g. named 'Iterator') and not only Implement the
> Interface then in your other container-class, but
> also create a hidden instance of your ICollection-
> Interface-Class.

> In the following example I've named this additional
> container-interface IOtherItems and not ICollection,
> but you should get the idea...

> '------------------Into a Class IOtherItems----------------
> Option Explicit

> Private mCol As Collection

> Private Sub Class_Initialize()
>   Set mCol = New Collection
> End Sub

> 'a helper, to hand out the internal Collection to the implementing Class
> Friend Function GetCol() As Collection
>   Set GetCol = mCol
> End Function

> '**********now the publically visible Interface-Def************
> '...
> 'ensure, you've set Proc-Attr to -4 for this function
> Public Function Iterator() As IUnknown
>   Set Iterator = mCol.[_NewEnum]
> End Function

> 'this is the rest of our interface, only with virtual Defs
> Public Sub Add(Item, Key)
> End Sub
> Public Sub Remove(Key)
> End Sub
> Public Property Get Item(Key) As cOtherItem
> End Property

> '------------------Into a Class cOtherItem----------------
> Option Explicit

> Public SomeLongInt As Long
> Public SomeString As String

> '------------------Into a Class cItem----------------
> Option Explicit

> Public SomeLongInt As Long
> Public SomeString As String

> '------------------Into a Class cItems----------------
> Option Explicit

> Private mCol As Collection 'for the normal cItem-Types

> Implements IOtherItems 'the Interface we want to implement...
> Private mIOtherItems As IOtherItems 'but we create an instance here also

> Private Sub Class_Initialize()
>   Set mCol = New Collection 'for the normal cItem-Types
>   Set mIOtherItems = New IOtherItems
> End Sub

> '*******everything in this block is for the normal cItem-Types******
> Public Sub Add(Item, Key)
>   mCol.Add Item, Key
> End Sub

> Public Sub Remove(Key)
>   mCol.Remove Key
> End Sub

> Public Property Get Item(Key) As cItem
>   Set Item = mCol(Key)
> End Property

> 'set Proc-Attr to -4 (and also "hidden", if you want that)
> Public Function Iterator() As IUnknown
>   Set Iterator = mCol.[_NewEnum]
> End Function
> '************end of the normal cItem-Types code-block************

> '*****and now the code-block for the IOthers-Implementation******
> Private Sub IOtherItems_Add(Item As Variant, Key As Variant)
>   mIOtherItems.GetCol.Add Item, Key
> End Sub

> Private Property Get IOtherItems_Item(Key As Variant) As cOtherItem
>   Set IOtherItems_Item = mIOtherItems.GetCol(Key)
> End Property

> Private Function IOtherItems_Iterator() As stdole.IUnknown
>   Set IOtherItems_Iterator = mIOtherItems.Iterator
> End Function

> Private Sub IOtherItems_Remove(Key As Variant)
>   mIOtherItems.GetCol.Remove Key
> End Sub

> '------------------Into a Form for testing----------------
> Option Explicit

> Private Sub Form_Load()
> Dim i As Long
> Dim Items As cItems
>   Set Items = New cItems 'instantiation against the Default-interface

>   'now we add some normal items into this container-instance
>   Dim NewItem As cItem
>   For i = 1 To 3
>     Set NewItem = New cItem
>     NewItem.SomeLongInt = i
>     NewItem.SomeString = "cItem" & i
>     Items.Add NewItem, "Key" & i
>   Next i

>   'now we only cast the container-instance against IOtherItems-interface
>   Dim OtherItems As IOtherItems
>   Set OtherItems = Items 'as said, we do only a cast here

>   'and add some cOtherItem(s) against this second container-interface
>   Dim NewOtherItem As cOtherItem
>   For i = 1 To 3
>     Set NewOtherItem = New cOtherItem
>     NewOtherItem.SomeLongInt = i
>     NewOtherItem.SomeString = "cOtherItem" & i
>     OtherItems.Add NewOtherItem, "Key" & i
>   Next i

>   'finally we should be able, to enumerate on
>   'both interfaces (of the same container-instance)
>   Dim Item As cItem
>   For Each Item In Items
>     Debug.Print Item.SomeString
>   Next Item

>   Debug.Print

>   'and the other items in that container (over the second interface)
>   Dim OtherItem As cOtherItem
>   For Each OtherItem In OtherItems
>     Debug.Print OtherItem.SomeString
>   Next OtherItem
> End Sub

> HTH,

> Olaf



Fri, 04 Nov 2011 23:56:15 GMT  
 NewEnum in Interface



Quote:
> I need to digest this  a bit ...

Yeah, these scenarios are always a bit difficult to describe -
therefore this concrete example (which also needs a bit of
effort, to "set up" and "copy over" all of the small classdefs -
and BTW, don't forget to set these -4-Proc-Attributes
on the routines where I've placed an appropriate comment).

But IMO the only way, to finally have something to
"talk about" or "refer to" in such cases.
In case I've misinterpret your first post somehow, feel
free to adjust the class-examples, to match better with
your scenario - and repost your concrete implementations
then - really easier to follow all that on such a concrete
"small code-base".

Olaf



Sat, 05 Nov 2011 00:37:58 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Exposing NEWENUM IUNKNOWN interface from a VBA Class mOdule

2. Problem with NewEnum using custom Interface written in IDL

3. setting procedure attribute NewEnum to -4??

4. Public Property Get NewEnum() As IUnknown

5. Class Builder NewEnum method

6. ASP, Collections, For...Each, NewEnum()

7. Custom collections and Dictionary objects NewEnum function

8. How can I create a class that exposes several different NewEnum's

9. NewEnum fails under COM+

10. Problems with a collection's NewEnum

11. NewEnum

12. problem with NewEnum method([out, retval] IUnknown** )

 

 
Powered by phpBB® Forum Software