Quali sono le alternative alle raccolte generiche per l'interoperabilità COM?
-
06-07-2019 - |
Domanda
Sto tentando di restituire una raccolta di reparti da un assembly .NET che verrà utilizzata da ASP tramite interoperabilità COM. Utilizzando .NET vorrei solo restituire una raccolta generica, ad es. List<Department>
, ma sembra che i generici non funzionino bene con l'interoperabilità COM. Quindi, quali sono le mie opzioni?
Vorrei sia scorrere l'elenco sia essere in grado di accedere a un elemento per indice. Devo ereditare da IList
, implementare un IList<Department>
, List[index]
o un'altra interfaccia o esiste un modo migliore? Idealmente, preferirei non dover implementare una raccolta personalizzata per ogni tipo di elenco di cui ho bisogno. Inoltre, <=> funzionerà anche con l'interoperabilità COM?
Grazie, Mike
Componenti .NET di esempio (C #):
public class Department {
public string Code { get; private set; }
public string Name { get; private set; }
// ...
}
public class MyLibrary {
public List<Department> GetDepartments() {
// return a list of Departments from the database
}
}
Esempio di codice ASP:
<%
Function PrintDepartments(departments)
Dim department
For Each department In departments
Response.Write(department.Code & ": " & department.Name & "<br />")
Next
End Function
Dim myLibrary, departments
Set myLibrary = Server.CreateObject("MyAssembly.MyLibrary")
Set departments = myLibrary.GetDepartments()
%>
<h1>Departments</h1>
<% Call PrintDepartments(departments) %>
<h1>The third department</h1>
<%= departments(2).Name %>
Domande correlate:
Soluzione
Dopo ulteriori ricerche e prove ed errori, penso di aver trovato una soluzione utilizzando System.Collections.ArrayList
. Tuttavia, questo non funziona con l'ottenimento di un valore per indice. Per fare ciò, ho creato una nuova classe ComArrayList
che eredita da ArrayList
e aggiunge nuovi metodi GetByIndex
e SetByIndex
.
Collezione compatibile con l'interoperabilità COM:
public class ComArrayList : System.Collections.ArrayList {
public virtual object GetByIndex(int index) {
return base[index];
}
public virtual void SetByIndex(int index, object value) {
base[index] = value;
}
}
Componente .NET aggiornato MyLibrary.GetDepartments:
public ComArrayList GetDepartments() {
// return a list of Departments from the database
}
ASP aggiornato:
<h1>The third department</h1>
<%= departments.GetByIndex(2).Name %>
Altri suggerimenti
Dato che stai utilizzando solo i dati in ASP, ti suggerirei di restituire Department[]
. Questo dovrebbe essere mappato direttamente a un SAFEARRAY in COM. Supporta anche l'enumerazione e l'accesso indicizzato.
public Department[] GetDepartments() {
var departments = new List<Department>();
// populate list from database
return departments.ToArray();
}
Nel tuo codice ASP, non potresti farlo?
<h1>The third department</h1>
<%= departments.Item(2).Name %>
So che in VB .NET, gli indicizzatori C # sono supportati tramite " Item " proprietà, quindi la stessa idea potrebbe funzionare in ASP.
Ho cercato di risolvere questo stesso problema in vb.net (non parla fluentemente C #).
Poiché List (Of T) supporta l'interfaccia IList, per l'interfaccia COM per i miei oggetti ho provato a specificare
Public Class MyClass
...
Private _MyList As List(of MyObject)
Public ReadOnly Property MyList As IList Implements IMyClass.MyList
Get
Return _MyList
End Get
End Property
e quindi specificando nell'interfaccia pubblica che COM vede
ReadOnly Property MyList As IList
Questo sembra funzionare bene da un classico client ASP che crea un'istanza dell'oggetto, chiama una funzione generatore e quindi legge la proprietà MyList come un array.