F r a n c e s c o   S m e l z o
Software engineering - Sistemi web - Formazione - Sicurezza - Privacy - IT consultant
Home e-mail

Come creare oggetti COM in .NET che supportino i cicli For Each in VB.Script e abbiano una proprietà predefinita

24/8/2005
di Francesco Smelzo
In ambiente Visual Basic (VB6, VBA VB.Script ecc...) siamo abituati a trovare, negli oggetti che rappresentano un insieme di elementi come le Collection delle funzionalità standard : il supporto al costrutto For Each ed una proprietà predefinita o default.
Prendiamo ad esempio un oggetto ADO come un recordset, in VB.Script (ad es. da ASP).
E' comune poter scorrere l'insieme Fields dell'oggetto Recordset in questo modo:
Set rs = CreateObject("ADODB.Recordset")
'... apre recordset
For Each f In rs.Fields
   Response.Write f.Value
Next
'...chiude recordset
Anzichè utilizzare un ciclo For...To come questo:
Set rs = CreateObject("ADODB.Recordset")
'... apre recordset
For i=0 to rs.Fields
   Response.Write f.Value
Next
'...chiude recordset
Altrettanto comune è riferirsi ad una proprietà predefinita di un'oggetto come:
Response.Write rs (0)
Anzinchè
rs.Fields.Item (0)
Quando creiamo un oggetto in .NET che intendiamo utilizzare da COM ci sono degli accorgimenti da adottare per mettere a disposizione queste funzionalità.
Ometto naturalmente di parlare di come esporre un oggetto .NET a COM (ulteriori spiegazioni le potete trovare nell'articolo How to call a Visual Basic .NET assembly from Visual Basic 6.0 and how to call a call Visual Basic COM component from Visual Basic .NET di Microsoft).
Partiamo quindi dal presupposto che avete creato una classe .net da esporre a COM come Collection. Una classe semplicissima che contiene:
  1. una lista ArrayList privata
  2. un metodo pubblico Add per aggiungere un oggetto
  3. una proprietà Item per ottenere un oggetto dalla lista utilizzando un indice
Questo è il codice :
<Guid("56A66686-22D8-4eab-8F02-9758A21F6EFB"), ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class MyCollection
    Private _list As ArrayList
	    Public ReadOnly Property list() As ArrayList
		Get
			If _list Is Nothing Then
                _list = New ArrayList
            End If
            Return _list
        End Get
    End Property

    Public Function Add(ByVal obj As Object) As Integer
        Return list.Add(obj)
    End Function
	
	Public ReadOnly Property Item(ByVal index As Integer) As Object
        Get
            Return list(index)
        End Get
    End Property
End Class
Per abilitare la funzionalità For...Each dai client VB.Script occorre implementare l'interfaccia IEnumerable ed il metodo GetEnumerator() mentre per definire la proprietà di default si deve aggiungere l'attributo DispId(0). Io l'ho fatto così:
<Guid("56A66686-22D8-4eab-8F02-9758A21F6EFB"), ClassInterface(ClassInterfaceType.AutoDual)> _
Public Class MyCollection
    Implements IEnumerable '<--implementa IEnumerable

    Private _list As ArrayList
    Public ReadOnly Property list() As ArrayList
        Get
            If _list Is Nothing Then
                _list = New ArrayList
            End If
            Return _list
        End Get
    End Property

    Public Function Add(ByVal obj As Object) As Integer
        Return list.Add(obj)
    End Function

	<DispId(0)> _ '<--Trasforma Item nella Default Property
    Public ReadOnly Property Item(ByVal index As Integer) As Object
        Get
            Return list(index)
        End Get
    End Property
	
	'implementa GetEnumerator
    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return Me.list.GetEnumerator
    End Function
End Class
Nota: è possibile omettere l'implementazione di IEnumerable quando si eredita la classe da un'oggetto Collection di .NET come ArrayList, HashTable ecc... perchè questi oggetti a loro volta implementano IEnumerable.
In questo modo il client VB.Script potrà utilizzare l'oggetto nel modo consueto:
set myColl = CreateObject("MyNamespace.MyCollection")
myColl.Add("Prova")
For Each s In myColl
	Response.Write s
Next
'oppure anche 
Response.Write myColl(0)

Controllo disponibilita'

Valid XHTML 1.0!



Riferimenti - Cell. 338 2556588    Mail: francesco@smelzo.it