MathGroup Archive 2004

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Mathematica + NETLink + CodeDom- Example 2

At 11:22 PM 12/28/2003, ToolmakerSteve wrote:
>(Follow on to [mg45085] NETLink - CREATING a new class?
>I have submitted this to support@wolfram,
>and explained that I hope it will be given to a programmer
>who is working on NETLink -

He's now back from vacation....

>so that the problems I encountered in mg45085 can be resolved,
>and so that some example like this can be included in the NETLink 
>in hopes that some other O-O .NET programmers can be enticed to use 

Back in mg45085, the problem was:

>"NET::nomethod: No public instance method named CompileAssemblyFromDom exists
>for the .NET type Microsoft.CSharp.CSharpCodeGenerator."

And the offending code was:

>     csharp = NETNew[ "Microsoft.CSharp.CSharpCodeProvider" ];
>     cscompiler = csharp@CreateCompiler[];
>     result = cscompiler@CompileAssemblyFromDom[ compParams, compUnit1 ];

The problem here is subtle, and it was a limitation in the first version of 
.NET/Link. The issue is that the actual class of the cscompiler object 
(Microsoft.CSharp.CSharpCodeGenerator) is private. Although this class 
implements the public ICodeCompiler interface, and therefore has a public 
method named CompileAssemblyFromDom, .NET/Link cannot invoke the method 
because the class is private. In a compiled .NET language program this is 
not a problem because the cscompiler object would be typed as the public 
ICodeCompiler interface, not its actual private runtime class type:

     // C# code.
     ICodeCompiler cscompiler = csharp.CreateCompiler();
     result = cscompiler.CompileAssemblyFromDom(...);

.NET/Link 1.1 includes a CastNETObject function that allows you to upcast 
the cscompiler object to the ICodeCompiler interface type. This would allow 
the method to be called just like in a C# program:

     cscompiler = CastNETObject[csharp@CreateCompiler[], 
     result = cscompiler@CompileAssemblyFromDom[ compParams, compUnit1 ];

The 1.1 version of .NET/Link ships with Mathematica 5.0.1 and will be 
available for general download in the very near future at

In the meantime, you can work around the problem by manually using 
reflection to invoke the CompileAssemblyFromDom method defined in the 
ICodeCompiler interface:

     iccType = 
     meth = iccType@GetMethod["CompileAssemblyFromDom"];
     result = meth@Invoke[cscompiler, {compParams, compUnit1}];

There is another small issue in your old and new code--the problem you had 
with doing a BitOr merging of the MemberAttributes`Public and 
MemberAttributes`Static enum values. Normally this will work in .NET/Link, 
and your NetBitOr function is the correct way to do (flag1 | flag2) 
constructions in Mathematica (this is documented in the new .NET/Link 1.1 
User Guide):

     NetBitOr[ net1_, net2_ ]:=
        BitOr[ NETObjectToExpression[ net1 ], NETObjectToExpression[ net2 ] ]

The reason it doesn't work for the MemberAttributes enum is that for some 
reason this enum is not decorated with the [Flags] attribute, which is 
supposed to be applied to all enums that can have values bitor-ed together. 
It looks like a bug in the .NET Framework that the [Flags] attribute was 
left off the MemberAttributes enum. You can work around the problem by 
manually constructing an enum value of the right type by using the .NET 
Framework's Enum.ToObject() function:

     memberAttributesType = 
     attrs = Enum`ToObject[memberAttributesType,

>Here is a more interesting notebook,
>which creates a .NET assembly without
>having to type all those "NETNew" expressions.
>It contains a package "NetCodeGen",
>which is a translator from a simple structure in Mathematica,
>which represents the assembly as code snippets within some structural
>(By The Way, this is far more readable than the XML version of code that some
>people are starting to work with in other environments.)

Your approach is interesting, and I suggest you continue developing it, 
especially with an eye to allowing users to provide method implementations 
in the Mathematica language instead of only embedding strings of C# code in 
a Mathematica expression structure. This is quite similar to work that was 
in the development version of .NET/Link but pulled out before release 
because it was beyond the scope of a 1.0 release. Basically, it was decided 
that there was not sufficient time for the considerable design work 
required. Methods like DefineNETClass and NETMethod were once part of 
.NET/Link. Presumably, functionality like this will be introduced in a 
future release.

Todd Gayley
Wolfram Research 

  • Prev by Date: Re: RunThrough on Windows 2000
  • Next by Date: Wishart Distribution
  • Previous by thread: Re: How to copy pattern from one expression to another?
  • Next by thread: Re: Mathematica + NETLink + CodeDom- Example 2