Compiling C# code from APLX

Although you won't need to do it very often, it's useful to be able to compile C# code directly from APLX. Situations when you might need to do so include:

Disclaimer

What's described here is not a 'conventional' way of accessing C# code. If you have a project that mixes APL and C#, the normal course would be to compile the C# code into a separate library using a tool like Microsoft's Visual Studio. This can then be accessed from APLX by making sure that the library is included in the APLX .NET search path.

See the following Wiki page Calling your own C# code from APLX for more information.

However, you may encounter occasions when dynamic compilation is useful.

Some sample C# code

Here's some sample C# code which we can use to demonstrate dynamic compilation:

using System;
using System.IO;
using System.Windows.Forms;
namespace MyNamespace
{
    public class MyClass
    {
        public int Add (int a, int b)
        {
            return a+b;
        }
    }
}

If the code is stored in a file on disk, we can read it using ⎕IMPORT, e.g.

      code←⎕IMPORT 'C:\simon\example.cs' 'txt'

Alternatively, here's the code in an APL variable if you want to try this example directly:

      code←''
      code←code,⊂'using System;'
      code←code,⊂'using System.IO;'
      code←code,⊂'using System.Windows.Forms;'
      code←code,⊂'namespace MyNamespace'
      code←code,⊂'{'
      code←code,⊂'    public class MyClass'
      code←code,⊂'    {'
      code←code,⊂'        public int Add (int a, int b)'
      code←code,⊂'        {'
      code←code,⊂'            return a+b;'
      code←code,⊂'        }'
      code←code,⊂'    }'
      code←code,⊂'}'

      code←∊code

Compiling code dynamically

Here's an example function which uses .NET to compile the code dynamically:

assembly←CompileCode code;CSharpCodeProvider;loParameters;objType;arrayType;codeArray;results;i;err
⍝ Argument 'code' is C# code to compile, as ⎕R-delimited vector
⍝ Result is compiled assembly

⍝ Create compiler
CSharpCodeProvider← '.net' ⎕new 'Microsoft.CSharp.CSharpCodeProvider'

⍝ Create parameters for compiler
loParameters← '.net' ⎕new 'System.CodeDom.Compiler.CompilerParameters'
loParameters.GenerateInMemory←1

⍝ Add reference assemblies. Note that these may vary depending on the C# code being compiled
⊣ loParameters.ReferencedAssemblies.Add 'System.dll'
⊣ loParameters.ReferencedAssemblies.Add 'System.Windows.Forms.dll'

⍝ Convert code to compile into an array containing a single string
objType←'.net' ⎕GETCLASS 'String'
arrayType←'.net' ⎕GETCLASS 'System.Array'
codeArray←arrayType.CreateInstance.⎕REF objType 1
codeArray.SetValue code 0

⍝ Compile it
results←CSharpCodeProvider.CompileAssemblyFromSource loParameters codeArray

⍝ Any errors?
:If results.Errors.Count=0
  ⍝ All OK
  assembly←results.CompiledAssembly
:Else
  ⍝ Report errors
  assembly←⎕NULL
  :For i :In (⍳results.Errors.Count)-⎕IO
    err←results.Errors.Item i
    'Error, Line: ',err.Line.ToString,' - ',err.ErrorText
  :EndFor   
:EndIf  

Testing the code

Here's how to create an instance of the MyClass class defined in the compiled code:

      ⍝ Compile the code (only need to do this once)
      assembly←CompileCode code
      
      ⍝ Create an instance of MyClass
      obj←assembly.CreateInstance 'MyNamespace.MyClass'

      ⍝ Did it work?
      obj.Add 3 4
7




Author: SimonMarsden


CategoryDotNet CategoryAplx

CompilingCSharp_from_APLX (last edited 2010-06-22 12:33:49 by SimonMarsden)