sorcery.png

There is a wonderful blog post about Generic types in X++. And as It says, the easiest way to work with generic types in X++ is to create .Net library and expose non-generic interface, because X++ compiler has lots of limitations.

However, if you really want to have some fun and stick to X++, it’s possible with a help of reflection.

Let’s say we have a C# class that accepts  List<string[]> and we want to invoke it from X++:

public class Class1
{
    public static string myMethod(List<string[]> list)
    {
        string res = string.Empty;

        foreach (var array in list)
        {
            foreach (string s in array)
            {
                res += s;
            }
        }
return res;
    }
}

We cannot simply declare:

var stringList = new System.Collections.Generic.List<String[]>();

Looks like X++ parser cannot handle “<” and “[” combination, as it gives “Invalid token ‘<‘. ” compile error.

Therefore, instead of 2 lines of code in C#:

var stringArrayList = new System.Collections.Generic.List<string[]> { new string[] { "a", "b", "c" } };
string res = Class1.myMethod(stringArrayList);

We need a bit more in X++:

System.String string;

//array we want to put into a list
System.String[] stringArray = new System.String[3]();
stringArray.SetValue('a', 0);
stringArray.SetValue('b', 1);
stringArray.SetValue('c', 2);

//Type[] array for MakeGenericType
System.Type[] typeParams = new  System.Type[1]();
typeParams.SetValue(string.GetType().MakeArrayType(), 0);

//instantiate System.Collections.Generic.List<String[]>
System.Type listType = System.Type::GetType("System.Collections.Generic.List`1");
var constructedListType = listType.MakeGenericType(typeParams);
var stringArrayList = System.Activator::CreateInstance(constructedListType);

//invoke "Add" using reflection because we cannot cast it back to List<String[]>
var  bindingFlags =  BindingFlags::Instance | BindingFlags::Public;
System.Reflection.MethodInfo methodsInfo = constructedListType.GetMethod("Add", bindingFlags);
System.Object[] params = new  System.Object[1]();
params.SetValue(stringArray, 0);
methodsInfo.Invoke(stringArrayList, params);

info(Class1::myMethod(stringArrayList));

X++ is lacking in .Net features and often it’s easier to create intermediate C# class library. However, as you can see, some limitations are caused by X++ compiler that could be overcome using reflection.