This week I wrote some C# code using .NET Interop to X++ and I needed to get records from a QueryRun object. You surely know how to do it in AX (by calling QueryRun.get()), nevertheless I wanted to do it in a slightly better way. My method is rather short, but it may be difficult to grasp, if you’re not too familiar with C#. It utilizes several great features that don’t exist in X++.
I had several requirements.
I wanted to call the method in a natural way, such as queryRun.GetTable(…), therefore I built it as an extension method.
I wanted a descriptive exception if the table doesn’t exist in the query.
I wanted to get the right type, such as LogisticsPostalAddress instead of Common (all these are .NET proxy classes for X++ objects). It means that the method must be generic and returning the generic type. I also constrained the generic type only to classes extending Common (T GetTable() where T: Common).
Unfortunately queryRun.get() returns an instance of the Common class, not instances of particular tables. Fortunately it’s possible to create the right table proxy by passing the Common object to the constructor (e.g. LogisticsPostalAddress(common)). But we can’t use parametrized constructors of generic types, therefore I ask the caller to provide a method that constructs the table proxy from Common.
I also wanted to avoid hard-coded table names and I decided to simply take the name of the generic type.
This is my implementation:
public static T GetTable(this QueryRun queryRun, Func<Common, T> creator, int occurence = 1) where T : Common { string tableName = typeof(T).Name; int tableId = Global.tableName2Id(tableName); Common common; try { common = queryRun.get(tableId, occurence); } catch (XppException) { throw new InvalidOperationException(String.Format("The query does not contain {0}", tableName)); } return creator(common); }
And this is how I use it, passing a lambda function as the argument:
var address = queryRun.GetTable(c => new LogisticsPostalAddress(c));
The C# compiler is smart enough to infer the return type and the type of the address variable just from the type returned by my lambda function.
Writing code like this is real fun!
Thanks for sharing this code.
I hope with AX becoming more and more part of .NET world, we’ll start getting all the cool features C# has that X++ doesn’t.
Maybe in AX 8 Microsoft will switch to C# completely, who knows.