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
    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.