>
1. Getting started
2. Calling methods
3. Working with .NET Objects
4. Fields and Properties
5. Methods Arguments
6. Nested Types
7. Enums
8. Arrays and Collections
9. Embeding UI controls
10. Referencing libraries
11. Off-line activation
12. Events and Delegates
13. Disposing and Garabage Collection
14. .NET Configuration Files (AppConfig, WebConfig)
15. Exceptions, Debugging and Testing
16. Strongly-Typed Wrappers
    17. Advanced Activation and Licensing
    18 Other usage scenarios
      Working with .NET arrays and collections with Javonet

      Data structures are one of the essential aspects of every piece of software that has ever been written. Any
      application, from simple command line util to scalable enterprise systems, constantly process various
      information, that very often require specific grouping and access strategies. This aspect is addressed by
      arrays and more advanced collection types available both in Java and .NET environments. By using the
      Javonet framework, Java users gain ability to easily and effectively work with data structures originating
      from .NET platform.

      Workspace

      For better readability, I’ll present respective code fragments, as we need them. From the perspective of the
      Java program, that I’ll be using throughout the examples, the main method’s skeleton is as follows:

      public static void main(String[] args) throws JavonetException {
      
        Javonet.activate(License.EMAIL, License.LICENSE_KEY, JavonetFramework.v45);
        Javonet.reference(Constants.DLL_FILE_PATH);
      
        useIntArrayExample();
        getIntArrayExample();
        getArrayOfIntArraysExample();
      
        useCustomObjectArrayExample();
        getCustomObjectArrayExample();
        getArrayOfCustomObjectArraysExample();
      
        useListExample();
        getListExample();
      
        useSetExample();
        getSetExample();
      
        useDictionaryExample();
        getDictionaryExample();
      
      }

      My aim here is to extract code for Javonet framework activation and referencing our .NET library as a
      common part of all the examples.

      Working with Arrays

      During the array part of this tutorial, I’ll be working with the following pseudo-service class, which main
      purpose is to produce and consume various array-typed objects.

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace ArraysAndCollections
      {
        class ArrayService
        {
        
          public int[] GetIntArray()
          {
            return new int[]{ 1, 2, 3, 4 };
          }
          
          public void UseIntArray(int[] intArray)
          {
            Console.WriteLine("[.NET] Contents of primitive-type array:");
            
            foreach (int intVal in intArray)
            {
              Console.WriteLine("{0} ", intVal);
            }
          }
          
          public int[][] GetArrayOfIntArrays()
          {
            int[][] arrayOfIntArrays = new int[2][];
            
            arrayOfIntArrays[0] = new int[4] { 1, 2, 3, 4 };
            arrayOfIntArrays[1] = new int[4] { 11, 22, 33, 44 };
            
            return arrayOfIntArrays;
          }
          
          public CustomObject[] GetCustomObjectArray()
          {
            return new CustomObject[]{ new CustomObject("A",1),
            new CustomObject("B", 2),
            new CustomObject("C", 3)};
          }
        
          public void UseCustomObjectArray(CustomObject[] cuArray)
          {
            Console.WriteLine("[.NET] Contents of the reference-type array:");
            
            foreach (CustomObject cu in cuArray)
            {
              Console.WriteLine("{0}[{1}] ", cu.Name, cu.Value);
            }
          }
        
          public CustomObject[][] GetArrayOfCustomObjectArrays()
          {
            CustomObject[][] arrayOfCustomObjectArrays = new CustomObject[2][];
            
            arrayOfCustomObjectArrays[0] = new CustomObject[]{
            new CustomObject("A1",1),
            new CustomObject("A2", 2),
            new CustomObject("A3", 3)};
            
            arrayOfCustomObjectArrays[1] = new CustomObject[]{
            new CustomObject("B1",1),
            new CustomObject("B2", 2),
            new CustomObject("B3", 3)};
            
            return arrayOfCustomObjectArrays;
          }
        }
        
        class CustomObject
        {
        
          public String Name { get; set; }
          public int Value { get; set; }
      
          public CustomObject(String name, int value)
          {
            this.Name = name;
            this.Value = value;
          }
        }
      }

      Retrieving and handling .NET array

      Javonet framework allows for simple retrieval of arrays of objects from .NET code, as presented in the
      following examples. Such objects are treated as usual Java arrays, therefore all the standard Java
      programming techniques apply. Although examples present objects’ retrieval in result to method calls, the
      same approach is applicable for getting class properties, direct member access etc.

      It’s worth mentioning that, when dealing with primitive, value-typed .NET arrays, Javonet framework
      automatically translates them to respective Java primitive type. In such cases, it is necessary to keep in
      mind, that the returned array will contain boxing-type objects, otherwise we might face an
      InvalidClassCastException.

      static void getIntArrayExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        
        Integer[] intArray = arrayService.invoke("GetIntArray");
        
        System.out.format("[Java] Contents of primitive-type array: %n");
        
        for (int intVal : intArray){
          System.out.format("%d%n", intVal);
        }
      }

      As for .NET arrays containing reference-type objects, we’re simply dealing with an NObject array. Working
      with such object is no different that for any other NObject provided by the framework from the .NET code.

      static void getCustomObjectArrayExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        NObject[] coArray = arrayService.invoke("GetCustomObjectArray");
        
        System.out.format("[Java] Contents of reference-type array: %n");
        
        for (NObject co : coArray){
          System.out.format("%s[%d]%n",
          co.get("Name"),
          co.get("Value"));
        }
      }

      In the previous examples, we’ve been retrieving a single-dimensional arrays. It is possible however, to get
      an array of arrays, either for primitive- and reference-type objects. Here are the examples:

      Value-typed nested arrays:

      static void getArrayOfIntArraysExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        NObject[] arrayOfIntArrays = arrayService.invoke("GetArrayOfIntArrays");
        
        System.out.format("[Java] Contents of primitive-type array of arrays: %n");
        
        for (NObject intArray : arrayOfIntArrays){
          
          for (int i = 0; i < intArray.<Integer>get("Length"); i++){
            
            System.out.format("%s ", intArray.<Integer>getIndex(i));
          
          }
        
            System.out.println();
        
        }
      }
      

      Reference-type nested arrays:

      static void getArrayOfCustomObjectArraysExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        NObject[] arrayOfCOArrays = arrayService.invoke("GetArrayOfCustomObjectArrays");
        
        System.out.format("[Java] Contents of reference-type array of arrays: %n");
        
        for (NObject coArray : arrayOfCOArrays){
      
          for (int i = 0; i < coArray.<Integer>get("Length"); i++){
      
            NObject co = coArray.getIndex(i);
            System.out.format("%s[%d] ",
            co.get("Name"),
            co.get("Value"));
      
          }
      
          System.out.println();
        }
      }
      

      Unfortunately, current version of Javonet framework does not support retrieval of arrays containing arraytype
      objects, nested more than once. Also, the multidimensional arrays (in the .NET way of things) are not
      supported either. Thankfully, despite the fact, that such cases are not that common and/or easy
      workarounds exist, it is considered as viable enhancement, which most probably will be shipped in one of
      the upcoming versions.

      Passing .NET array

      Being aware of the automatic type conversion for value-typed arrays, it is absolutely safe to pass regular
      Java arrays as arguments to the .NET code. Similarily as when retrieving primitive arrays, it is necessary to
      work with the boxed wrappers.

      static void useIntArrayExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        
        Integer[] intArray = { 1, 2, 3, 4};
        
        arrayService.invoke("UseIntArray", new Object[]{intArray});
      }

      In case we need to send a reference-type array, all we need to do is create an array of NObjects and
      populate it, as shown in the next example.

      static void useCustomObjectArrayExample() throws JavonetException{
        
        NObject arrayService = Javonet.New("ArrayService");
        
        NObject[] cuArray = {
          Javonet.New("CustomObject", "D", 1),
          Javonet.New("CustomObject", "E", 2)
        };
        
        arrayService.invoke("UseCustomObjectArray", new Object[]{cuArray});
      }

      Unlike the array-retrieval scenario, sending nested arrays is not supported at the moment, it is however
      considered for shipment, depending on the demand for such feature.

      Working with collections

      For the collection part of this tutorial, I’ll be using the following .NET class. Similarily as in the previous
      section, this code’s main responsibility is to produce and consume various collection types.

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace ArraysAndCollections
      {
        class CollectionService
        {
          public IList<string> GetList()
          {
            return new List<string> { "strings", "in", "list", "from", ".NET" };
          }
          
          public void UseList(List<string> list)
          {
            Console.WriteLine("[.NET] List contents:");
            
            foreach (string element in list)
            {
              Console.WriteLine("{0} ", element);
            }
          }
          
          public <string> GetSet()
          {
            return new HashSet<string>{"strings", "in", "set", "from", ".NET"};
          }
          
          public void UseSet(ISet<string> set)
          {
            Console.WriteLine("[.NET] Set contents:");
            
            foreach (string element in set)
            {
              Console.WriteLine("{0} ", element);
            }
          }
          
          public IDictionary<string, string> GetDictionary()
          {
            return new Dictionary<string, string>()
            {
              {"key1","value1"},
              {"key2","value2"},
              {"key3","value3"}
            };
          }
          
          public void UseDictionary(IDictionary<string, string> dictionary)
          {
            Console.WriteLine("[.NET] Dictionary contents:");
            
            foreach (string key in dictionary.Keys)
            {
              Console.WriteLine("'{0}' = '{1}'", key, dictionary[key]);
            }
          }
        }
      }

      Retrieving and handling .NET collections

      As it is easy to guess, .NET collection-type objects retrieved by the Javonet framework, are accessible via
      the NObject class instances on the Java side. Therefore working with these objects is really simple, as I’ll
      show in the next few examples.

      Thefollowing code retrieves an instance of a Set<String> class by invoking the parameterless “GetSet”
      method of the CollectionService object. We can access various attributes of our set with the
      NObject.get(String propertyName, Object… args) or invoke any of its availablbe methods using
      NObject.invoke(String methodName, Object… args). It’s worth mentioning that the result type of
      these methods can be parametrized, relieving us from manual type-checking-and-casting steps.

      In the example below, we’re using this approach to check the size of the received Set<String> object, as
      well as use the collection enumerator object, to iterate over the contained strings. Unfortunately, as the
      NObject class doea not implement Java Iterable interface, it is not possible to simply use the NObject in
      the for-each loop. Also, since set does not allow for index-based access to the contained elements, using
      enumerator can be considered primary method of collection traversal.

      static void getSetExample() throws JavonetException{
        
        NObject collectionService = Javonet.New("CollectionService");
        NObject list = collectionService.invoke("GetSet");
        
        // check size
        System.out.format("[Java] Set size: %d%n", list.<Integer>get("Count"));
        
        // iterate over contents
        System.out.format("[Java] Set contents:%n");
        
        NObject enumerator = list.invoke("GetEnumerator");
        
        while (enumerator.<Boolean>invoke("MoveNext")){
          String current = enumerator.get("Current");
          System.out.format("%s%n", current);
        }
      }

      In contrast to sets, lists and dictionaries do allow its users for selective access to the contained objects. For
      this purpose, we’ll be using the NObject.getIndex(Object index) method, which is only applicable for
      NObjects representing .NET types allowing for such access. In case you would try to invoke this method
      on a non-indexed .NET object, Javonet framework will throw a JavonetException, stating that given .NET
      class does not provide indexed values.

      The following two examples present usage of this approach against List<String> and
      Dictionary<String, String> objects retrieved from .NET code.

      static void getListExample() throws JavonetException{
        
        NObject collectionService = Javonet.New("CollectionService");
        
        NObject list = collectionService.invoke("GetList");
        
        // check size
        System.out.format("[Java] List size: %d%n", list.<Integer>get("Count"));
        
        // get arbitrary value assigned to given key
        System.out.format("[Java] Second element: %s%n", list.<String>getIndex(1));
        
        // iterate over contents
        System.out.format("[Java] List contents:%n");
        
        NObject enumerator = list.invoke("GetEnumerator");
        
        while (enumerator.<Boolean>invoke("MoveNext")){
          String current = enumerator.get("Current");
          System.out.format("%s%n", current);
        }
      }
      static void getDictionaryExample() throws JavonetException{
        
        NObject collectionService = Javonet.New("CollectionService");
        
        NObject dictionary = collectionService.invoke("GetDictionary");
        
        // check size
        System.out.format("[Java] Dictionary size: %d%n", dictionary.<Integer>get("Count"));
        
        // get arbitrary value assigned to given key
        System.out.format("[Java] Value for '%s' key: %s%n", "key1", dictionary.getIndex("key1"));
        
        // iterate over contents
        System.out.format("[Java] Dictionary contents:%n");
        
        NObject enumerator = dictionary.invoke("GetEnumerator");
        
        while (enumerator.<Boolean>invoke("MoveNext")){
          NObject current = enumerator.get("Current");
          System.out.format("'%s' = '%s'%n", current.get("Key"), current.get("Value"));
        }
      }

      Passing .NET collections

      Sending collection-type objects from Java to .NET is no different from passing any other object. All we are
      required to do is grab the NObject instance, representing specific .NET collection object and use it in the
      method call. In the following example, we’ll instantiate, populate and send a simple .NET list of strings as
      an argument to the “UseList” method of our .NET CollectionService object. This should result in printing
      all of the list’s contents to standard output stream.

      As I’ll be using parametrized versions of .NET collection types, I am assuming you are familiar with the
      Javonet-way of instantiating such objects. In case you’re not, I strongly encourage you to have a look at
      respective section of Quick Guide, available on the Javonet home page.

      Similarily as when retrieving collections from .NET, the approach for sending NObject instances as
      arguments of method calls, can also be applied for setting .NET object’s properties etc.

      static void useListExample() throws JavonetException{
          
        // get generic type with a single type-parameter
        NType listType = Javonet.getType("List`1", "String");
        
        // instantiate new object of that type
        NObject list = listType.create();
        
        // use object, to add dictionary entries
        list.invoke("Add", "Strings");
        list.invoke("Add", "in");
        list.invoke("Add", "the");
        list.invoke("Add", "list");
        list.invoke("Add", "from");
        list.invoke("Add", "Java");
        
        NObject collectionService = Javonet.New("CollectionService");
        
        collectionService.invoke("UseList", list);
      }

      Here’s another example in which we’re creating a Dictionary<String,String> object, populate it and
      pass it as an argument to our .NET CollectionService object’s “UseDictionary” method. Exactly as in
      previous example, we should get contents of our dictionary object in the standard output stream.

      static void useDictionaryExample() throws JavonetException{
        
        // get generic type with two type-parameters
        NType dictionaryType = Javonet.getType("Dictionary`2","String","String");
        
        // instantiate new object of that type
        NObject dictionary = dictionaryType.create();
        
        // use object, to add dictionary entries
        dictionary.invoke("Add", "key1","value1");
        dictionary.invoke("Add", "key2","value2");
        dictionary.invoke("Add", "key3","value3");
        
        NObject collectionService = Javonet.New("CollectionService");
        
        collectionService.invoke("UseDictionary", dictionary);  
      }

      Summary

      In this article we’ve focused on working with .NET arrays and collections in Java code using Javonet
      framework. As for array objects, differences of handling arrays of value- and reference-type objects have
      been discussed, as well as framework’s current limitations have been presented. We’ve briefly explained
      basic techniques of handling .NET collection objects, covering retrieval, enumeration- and index-based
      access to their contents, as well as instantiation and usage as arguments in the method calls.