Strongly-Typed Generic Collections
- Mark Juras
gmStudio can help you upgrade VB6 Collection and COM Scripting.Dictionary to strongly-typed Generic collections types . The Generic Collection class and the types it uses depend on usage of the instances of Collection and Dictionary in the application.
- List<T> is used for VB6.Collection having elements of type T wit only index access.
- Dictionary<K,T> is used for Scripting.Dictionary and Collections that require keyed access using keys of type K and having elements of type T.
- gmRTL.Core.OrderedDictionary<K,T> is used forVB6. Collections that require both keyed and ordered access using keys of type K and having elements of type T.
Simply stated the command takes original VB6 code like this:
Private col1 As VBA.Collection Private col2 As VBA.Collection Private col3 As VBA.Collection ... Private Sub AddItem(ByVal i_Item As String) col1.Add(i_Item) col2.Add(i_Item, i_Item) End Sub Private Sub AddItemWithKey(ByVal i_Key As String, ByVal i_Item As String) col3.Add(i_Item,i_Key) End Sub Private Sub Class_Initialize() col1 = New Collection col2 = New Collection col3 = New Collection End Sub
into target .NET code like this:
private List<string> col1; private List<string> col2; private Dictionary <string, string> col3; ... private void AddItem(string i_Item) { col1.Add(i_Item); col2.Add(i_Item); } private void AddItemWithKey(string i_Key, string i_Item) { col3.Add(i_Key, i_Item); } public Class1() { col1 = new List<string>(); col2 = new List<string>(); col3 = new Dictionary<string, string>(); }
Of course, there are many other environments in which collections are used, such as for-loops and enumerators are dealt with as well.
The strongly-typed generics upgrade is an advanced upgrade feature. It is designed to be used after the standard upgrade produces correctly-typed, build-complete results. Contact Great Migrations for assistance with using this feature.
Activating the Generic Collections Upgrade
The Generic Collections upgrade is implemented as a gmNI DLL that extends the core tool. You may activate this feature by loading this DLL with a <Select GenericCollections=on/> element before the Compile element in your translation script. These elements must also be placed prior to any <Reference or <Compile element.
<Select GenericCollections="on" /> ... <Compile>...</Compile>
De-Activating the Generic Collections Upgrade
<Select GenericCollections="on" /> ... <Compile>...</Compile> ... <Collections Collection="off" Dictionary="off" />
Reporting the Generic Collections Upgrade Activity
To write generic collection type inference activity to a file add
<Collections Report="<filepath>">
To write generic collection type inference activity to the translation log add
<Collections Report="on">
The report will contain DictionaryAdd and CollectionAdd statements that you can analyse and manually modify then include in your translation script to optimize the upgrade process.
Inference Options
TypeFromSetter
To infer type of dict<K,T> based on dict[InstanceOfK] = InstanceOfT based on element assignments:
<Collections TypeFromSetter="on">
For example:
Given this VB6:
Public Sub InitialiseDictionary1(dic As Dictionary) dic(1) = "nine" <--- The setter.key is int, and the setter.value is string. End Sub
we get this C#:
public static void InitialiseDictionary1(Dictionary<object,object> dic) { dic[1] = "nine"; <--- The setter.key is int, and the setter.value is string. }
The desired C# is
public static void InitialiseDictionary1(Dictionary<int,string> dic)
TypeFromExists
To inference type of dict<K,T> based on dict.Exists(K) tests
<Collections TypeFromExists ="on">
Optimizing the Generic Collections Upgrade for specific variables
The DictionaryAdd scripting command placed after <Compile> and before <Analyse> allows the user to specify how a Scripting.Dictionary in the source should be upgraded to a generic collection or dictionary in the generated code.
<DictionaryAdd identifier="FullName" Key="KeyType" Item="ItemType" /> ... <Analyse/>
If you are using ScriptRules, these optimizations will be placed in a PostAnalyse element.
<PreAnalyse Condition="%SrcName%=='Project1'"> <CollectionAdd identifier="Project1.CSort.CollectionSwap.n" Key="Variant" Item="Variant" Ordered="on"/> </PreAnalyse>
The DictionaryAdd script command has three attributes as follows:
Attribute | Description |
Identifier | Specifies the fully qualified name of a Dictionary symbol in the source project. |
Key | Specifies the key type for the dictionary. Must use type names from the source platform. |
Item | If present, specifies the item type for the dictionary. Must use type names from the source platform. |
If the identifier cannot be located, then the command is simply ignored. If the identifier does not identify a Dictionary, then the command is simply ignored.
The CollectionAdd scripting command placed after <Compile> and before <Analyse> allows the user to specify how a VB6.Collection in the source should be upgraded to a generic collection or dictionary in the generated code.
<CollectionAdd identifier="FullName" Key="KeyType" Item="ItemType" Ordered="on|off"/> ... <Analyse />
The CollectionAdd script command has four attributes as follows:
Attribute | Description |
Identifier | Specifies the fully qualified name of a Collection symbol in the source project. |
Key | Specifies the key type for the dictionary. Must use type names from the source platform. |
Item | If present, specifies the item type for the dictionary. Must use type names from the source platform |
Ordered | If set to on, specifies the target type is an OrderedDictionary |
If the identifier cannot be located, then the command is simply ignored. If the identifier does not identify a Collection, then the command is simply ignored.
Setting the Default for CollectionAdd@Ordered
If most of your collections should be migrated to an OrderedDictionary you should set DefaultOrdered=on. Exceptions to the default must be set using <CollectionAdd ... ordered="off" /> as described above.
<Collections DefaultOrdered="on">