Try..Catch for .NET Interoperability

While it may be a cold day in hell before we see any TRY..CATCH constructs in pure C/AL, we are all far more lucky when it comes to .NET interoperability. In this blog post I’ll (re)present the same concept I demonstrated during NAV TechDays 2013 last year in Antwerp, because I am quite sure this nifty little trick got lost under piles of other posts on this blog.

So, let’s learn how to do try..catch..finally for .NET interoperability C/AL code, using mostly C/AL code.

I say “mostly”, because to implement a try..catch..finally construct in C/AL we need an external .NET assembly.

Let’s start by taking a look at a simple chunk of C/AL code:

image

Nice, isn’t it?

(If it wasn’t obvious, F is of the System.IO.FileInfo type.)

Now, this piece of code can fail for whatever reason.  File may not be found. File may be in use. File my be inaccessible due to security permissions. Probably something else as well.

If you want to catch that error, though, you are out of options. One option is to call this codeunit from another object with the IF CODEUNIT.RUN construct, which is typically frowned upon because it complicates the code unnecessarily, and it demands a new codeunit object for every possible catchable operation and always causes licensing implications.

We don’t have any TRY..CATCH in C/AL, but we do have somethingelse: .NET interoperability, which has events. For a moment, consider this code:

image

Let’s theorize for a moment. Since C/AL fully supports .NET events, and since .NET supports try..catch..finally syntax, we can write a simple class that has two events: Catch and Finally. It can execute anything within a try block, and then in its catch and finally blocks it can raise the Catch and Finally events, respectively. Just like in the code above.

But of course not, the code above cannot just work. For it to work, we must make sure that whatever C/AL code we want to raise the Catch or Finally events for must run within a try..catch..finally block inside the TryCatchHelper class. So, how do we make our F.Delete method call execute inside this helper class’ try..catch..finally block?

Reflection.

Instead of calling our Delete method directly on the F object, we insteaad pass the object instance, the method name, and any parameters to a method on the TryCatchHelper class, which then executes this method on our behalf within a try..catch..finally block.

This is what this C/AL code should look like, with all the “magic” replaced by the actual code:

image

We first instantiate the list of parameters (the List object), then we instantiate the TryCatchHelper class, then we instantiate the F object. And then, instead of calling F.Delete, we actually call the TryCatchHelper’s TryCatchFinally method. Inside this method, we get hold of the MethodInfo instance for the method named ‘Delete’, call it on the object F, and pass to it the parameter list. Simple.

This TryCatchHelper class needs to have three methods: TryCatch, TryFinally, and TryCatchFinally, to support all three possibly try..catch..finally constructs.

And, finally, this is the TryCatchFinally class in C#:

Okay, I must admit that the class is not nearly as simple as I suggested at the beginning, because getting a MethodInfo from an object is not all that simple as it may seem at first. You must take care of whether methods are static or instance, whether they are generic or if any of their parameters are generic, and also – the catchiest part: you must make sure that the proper method info is detected based on assignability of actual to formal parameters (there is inheritance, interfaces, and explicit typecasting, all of which work with method calls, but actual and formal parameter types may vary). The class is documented, so you can try to figure it out on your own, I’ll rest my case for today.

Please let me know how you like this solution, and please abuse it to your liking.

2 thoughts on “Try..Catch for .NET Interoperability”

  1. Thanks for sharing this Vjeko.

    My feedback would be that, with C/AL now being converted to C# anyway, it would be worth the effort if Microsoft implemented Try, Catch, Finally in C/AL. After all, it is “just” something that the converter should understand.

    We are very close to have C/AL.NET anyway, this would be a major step.

  2. Yes, it would be perfect, but then we have the same considerations that I talked about in http://vjeko.com/blog/try-catch-in-cal

    Transaction simplicity in C/AL is one of its strong points, and it would have to go if we would get 100% C# in place of C/AL, so I think it’s going to be a long way before we get anywhere close to having full TRY..CATCH in C/AL. However, what would really solve a lot of problems, and make tricks such as this simpler, would be if we got full support for delegates in C/AL.

Leave a Reply