Re: Mathematica + NETLink + CodeDom- Example 2
- To: mathgroup at smc.vnet.net
- Subject: [mg45356] Re: [mg45304] Mathematica + NETLink + CodeDom- Example 2
- From: Todd Gayley <tgayley at wolfram.com>
- Date: Fri, 2 Jan 2004 04:23:45 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
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
>documentation,
>in hopes that some other O-O .NET programmers can be enticed to use
>Mathematica.
>)
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[],
"System.CodeDom.Compiler.ICodeCompiler"];
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
www.wolfram.com/solutions/mathlink/netlink.
In the meantime, you can work around the problem by manually using
reflection to invoke the CompileAssemblyFromDom method defined in the
ICodeCompiler interface:
iccType =
GetTypeObject[LoadNETType["System.CodeDom.Compiler.ICodeCompiler"]];
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 =
GetTypeObject[LoadNETType["System.CodeDom.MemberAttributes"]];
LoadNETType["System.Enum"];
attrs = Enum`ToObject[memberAttributesType,
MakeNETObject[NetBitOr[MemberAttributes`Public,
MemberAttributes`Static]]];
>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
>constructs.
>
>(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
- Follow-Ups:
- Re: Re: Mathematica + NETLink + CodeDom-Example 2
- From: Todd Gayley <tgayley@wolfram.com>
- Re: Mathematica + NETLink + CodeDom- Example 2
- From: "murphee (Werner Schuster)" <werner.schuster@netway.at>
- Re: Re: Mathematica + NETLink + CodeDom-Example 2