Casting CLR-objects with X++

Casting CLR-objects with X++ isn’t that obvious as it is in .Net languages as C# or even VB.Net. The following code will not compile because of the incompatibility of the two types System.Net.WebRequest and System.Net.HttpWebRequest even if you are allowed to upcast in any .Net language the WebRequest easily to HttpWebRequest.

    1:  System.Net.WebRequest webRequest;
    2:  System.Net.HttpWebRequest     httpWebRequest;
    3:  System.Net.HttpWebResponse    httpWebResponse;
    4:   
    5:  InteropPermission permission;
    6:  ;
    7:   
    8:      permission = new InteropPermission(InteropKind::ClrInterop);
    9:      permission.assert();
   10:   
   11:      webRequest = System.Net.WebRequest::Create("<your Url>");
   12:      try
   13:      {
   14:          webRequest.set_Credentials(System.Net.CredentialCache::get_DefaultCredentials());
   15:          //this will not work since we can't assign an 
   16:          //object of type WebRequest to the variable
   17:          //httpWebRequest which has the type HttpWebRequest. 
   18:          //In C# we would do this with a simple upcasting, 
   19:          // (httpWebRequest = (HttpWebRequest) webRequest;)
   20:          //but in X++ it isn't possible to do it this way.
   21:          //So the following instruction will cause the compiler error:
   22:          //"Operand types are not compatible with the operator."
   23:          httpWebRequest = webRequest; 
   24:   
   25:          httpResponse = httpWebRequest.GetResponse();
   26:      }
   27:      catch(Exception::CLRError)
   28:      {
   29:          //we'll discuss this later...
   30:      }

So line 23 will cause the compiler error:

“Operand types are not compatible with the operator.”

A workaround might be writing an external library that will cast that object in a .Net language (here it’s C#) like this:

    1:  using System;
    2:  using System.Net;
    3:   
    4:  namespace WebObjectConverter
    5:  {
    6:      public class Converter
    7:      {
    8:          public static HttpWebRequest WebRequest2HttpWebRequest(WebRequest request)
    9:          {
   10:              return (HttpWebRequest) request;
   11:          }
   12:      }
   13:  }

Since this isn’t a straight forward solution and this would probably require the deployment of an additional component, an other solution might be the following code:

    1:  CLRObject request;
    2:  System.Net.HttpWebRequest     httpWebRequest;
    3:  System.Net.HttpWebResponse    httpWebResponse;
    4:   
    5:  InteropPermission permission;
    6:  ;
    7:   
    8:      permission = new InteropPermission(InteropKind::ClrInterop);
    9:      permission.assert();
   10:   
   11:      request = System.Net.WebRequest::Create("<your Url>");
   12:      try
   13:      {
   14:          request.set_Credentials(System.Net.CredentialCache::get_DefaultCredentials());
   15:          httpWebRequest = request;
   16:   
   17:          httpWebResponse = httpWebRequest.GetResponse();
   18:      }
   19:      catch(Exception::CLRError)
   20:      {
   21:          //we'll discuss this later...
   22:      }

This code does use the unspecific type CLRObject instead of the specific type WebRequest. The advantage of using CLRObject in this case is, that the X++ compiler does now accept that you assign the WebRequest object (hold by the the variable “request”) to the HttpWebRequest-variable. You can call all properties or methods, that belongs to the type WebRequest like “set_Credentials” in line 14, but unfortunately you can’t use the intellisense and the compiler will not verify the use of this object as he would do by using the specific type.

So you can up- or downcast CLR-types in X++, but only if the object is referenced by a variable of the type CLRObject.