Mono.CSharp (Compiler as a Service) changes in version 2.10 - c#

I am running Mono version 2.10 on Ubuntu 11.10. I am trying to run the sample provided on http://blog.davidebbo.com/2012/02/quick-fun-with-monos-csharp-compiler-as.html ,but it seems to target a different version of mono. For instance Compile is a static method on Evaluator. I have made the following changes to his sample, but haven't got it working. Can anyone provide the correct changes, and does anyone know if there is any info on the API changes to Mono.CSharp? The version reported by my compiler is as follows:
$ dmcs --version
Mono C# compiler version 2.10.5.0
I compiled the following code using this command line:
dmcs -r:Mono.CSharp Sample.cs
And got this warning when compiling.
dmcs -r:Mono.CSharp Sample.cs
Sample.cs(26,17): warning CS0219: The variable `compiledMethod' is assigned but its value is never used
Compilation succeeded - 1 warning(s)
This is the result of running the code:
$ ./Sample.exe
{interactive}(2,40): error CS1525: Unexpected symbol `namespace', expecting `end-of-file' or `using'
{interactive}(4,70): error CS0101: The namespace `UserCode' already contains a definition for `Foo'
{interactive}(4,70): (Location of the symbol related to previous error)
This is the Code I have so far:
using System;
using System.IO;
using Mono.CSharp;
using System.Reflection;
namespace Sample
{
public interface IFoo { string Bar(string s); }
class Program
{
const string code = #"
using System;
namespace UserCode
{
public class Foo : Sample.IFoo
{
public string Bar(string s) { return s.ToUpper(); }
}
}
";
static void Main(string[] args)
{
Mono.CSharp.Evaluator.Init(new string[] {} );
Evaluator.ReferenceAssembly(Assembly.GetExecutingAssembly());
var compiledMethod = Evaluator.Compile(code);
for (;;)
{
string line = Console.ReadLine();
if (line == null) break;
object result;
bool result_set;
Evaluator.Evaluate(line, out result, out result_set);
if (result_set) Console.WriteLine(result);
}
}
}
}

Mono 2.10 comes with Evaluator supporting expressions and statements only. Your code contains type declaration which is not supported by Mono 2.10.
Mono 2.11 or git master Mono.CSharp have support for type declarations and other advanced features.

According to this: http://www.mono-project.com/Release_Notes_Mono_2.12#Instance_API , the static/global Evaluator is the older API and the Instance API is the newer one. The Mono I have is the current stable version (2.10) and Mono.CSharp that comes with version 2.11 has the instance methods. 2.12 doesn't look to have been released yet.
Here's another mention of the instance API to the Compiler as a service: http://tirania.org/blog/archive/2011/Oct-14.html

Related

Compiling c# in linux using mcs compiler gives error : The type or namespace name `Forms' does not exist in the namespace `System.Windows'?

I am trying to compile some c# code in linux, i can compile the same code in Windows using the csc command in Visual Studio command line. I also have already installed mono-devel.
this is the exact error :
mycode.cs(8,22): error CS0234: The type or namespace name `Forms' does not exist in the namespace `System.Windows'. Are you missing `System.Windows.Forms' assembly reference?
mycode.cs(70,27): error CS0246: The type or namespace name `Form' could not be found. Are you missing an assembly reference?
Why is this happening and how to fix it?
this is the command I'm using to compile it in linux :
mcs mycode.cs
and inside the code, Windows forms is already included :
using System.Windows.Forms;
also simple hello world code does get compiled without any error, i basically followed this blogpost about how to compile c# code in linux to set everything up :
https://jonsson.xyz/2016/11/23/csharp-linux/
Have you tried compiling with -r:System.Windows.Forms.dll ?
for example:
wc.cs:
using System.Windows.Forms;
public class Program
{
[STAThread]
public static void Main()
{
var f = new Form();
f.Text = "Hello World";
Application.Run(f);
}
}
then run:
$ mono-csc wf.cs -r:System.Windows.Forms.dll
and you get wf.exe

ScriptCS 0.17.01 Error Unexpected named argument

I tried to run my program using Visual Studio's Coderunner extension as well as from terminal with the scriptcs command.
My code is as follows:
using System;
namespace HelloWorldApplication {
class HelloWorld {
static void Main(string[] args) {
Console.WriteLine("hellowol");
}
}
}
The error message reads:
Unexpected named argument: Users/jfitz/Projects/C#/Projtest/test.cs
As mentioned in scriptcs/scriptcs issue 1188, this is from a scriptcs bug, which will be fixed in the next release (PR 1289 and commit 9e49b72)
In the meantime, pending the next 0.18 scriptcs release:
The workaround is the following:
instead of doing
mono scriptcs.exe /path/to/foo.csx
do:
mono scriptcs.exe -script /path/to/foo.csx
Jonas suggests in the comments:
For Visual Studio Code, add this to settings.json:
"code-runner.executorMap": { "csharp": "scriptcs -script" }

Can't change C# version in project's subfolders

In my project, I've tried to tidy up the structure a bit and put all the C# classes into a separate folder (App_Code).
The problem is that it seems even if the project is set to use C# 7.1 (and .net framework 4.7)
Trying to create in subfolder class with newer syntax in example:
Namespace MyProject {
public static class Class1
{ (//*****Available since C# 6.0****)
public static string Test1 { get; } = ConfigurationManager.AppSettings["User"];
public static int Test2 ()
{
string s = "10";
int.TryParse(s, out int y); //*****Available since C# 7.0
return y;
}
}
This causes a compilation error stating, that this feature requires version 6.x (or 7.x in the case of "Test2" above) instead of 5.0.
Intelisense prompts me to change the version but even after following the prompt
the error persists.
Not sure if it matters, but classes in the App_Code folder have the same namespace as the ones in the rest of the project.
I use VS 2017 Pro.

Detect c# version at compile time

I have an old line of c# code that looks basically like this:
foo.set_Parent(parent);
It has compiled fine for years. Now in VS2015 I get the error:
CS0571 'Foo.Parent.set': cannot explicitly call operator or accessor
So I can rewrite the line as:
foo.Parent=parent;
This builds fine in VS2015, but in VS2013 it gives the error:
'Foo.Parent' is not supported by the language; try directly calling
accessor methods 'Foo.get_Parent()' or Foo.set_Parent(Foo)'
So the simple fix is to simply ifdef these two lines based upon which version of the compiler is running. But how do you detect which version of the compiler is executing?
And for the record, no, I can't just dictate that everyone on the team simultaneously upgrades to VS2015.
Additional info -
For everyone smelling a rat, I'll go ahead and drag out the ugly truth, although I don't think it will change much of anything. The class Foo is from an ancient Borland assembly that is all bound up in Delphi (and yes, we're migrating away but not there yet). So the actual code, that compiles up to VS2013, looks like this:
using Borland.Vcl;
using RepGen;
using SnapReportsForm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace MigrantCOM {
[ComVisible(true)]
[Guid("48245BA3-736B-4F98-BDC5-AD86F77E39F4")]
[ProgId("MigrantCOM.Exports")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class MigrantCLRExports { // : MarshalByRefObject
public string Test(string s) { return s+s; }
}
[ComVisible(true)]
[Guid("1154D364-B588-4C31-88B9-141072303117")]
[ProgId("MigrantCOM.SnapRepCOM")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SnapRepCOM {
TRepGen repGen;
TStringList snapRefs=new TStringList();
TForm parent=new TForm(null);
TMemo designerMemo;
List<TReference> references=new List<TReference>();
TRunAsSnapContext runAsSnapContext=new TRunAsSnapContext();
public SnapRepCOM() {
designerMemo=new TMemo(parent); designerMemo.set_Parent(parent);
...
}
So the class being instantiated is Borland.Vcl.TMemo which is part of the old Delphi assembly.
I'm leaving this as an answer, linking an image will fit better here than in a comment.
So if you want to use VS 2015 but still use the same good ol' version of the C# language that worked for years, you can configure your project to target a specific version:
This adds <LangVersion>5</LangVersion> in the csproj.

How do I use the Mono.CSharp interpreter in Microsoft.NET

I was under the impression Mono's compiler was usable in Microsoft.NET
edit: updated blog posting here that I originally missed that explains some of it (is consistent with Justin's answers)
I created a simple class to try to use it
[TestFixture]
class Class1
{
[Test]
public void EXPR()
{
Evaluator.Run("using System;");
int sum = (int)Evaluator.Evaluate("1+2");
}
}
And a project in Visual Studio 2010 that references C:\Program Files (x86)\Mono-2.10.1\lib\mono\4.0\Mono.CSharp.dll.
However when I try to run this task I get the following exception, thrown at the Evaluator.Run call:
System.TypeInitializationException was unhandled by user code
Message=The type initializer for 'Mono.CSharp.Evaluator' threw an exception.
Source=Mono.CSharp
TypeName=Mono.CSharp.Evaluator
StackTrace:
at Mono.CSharp.Evaluator.Run(String statement)
at Experiments.Class1.EXPR() in W:\Experiments\Class1.cs:line 16
InnerException: System.TypeLoadException
Message=Method 'Mono.CSharp.Location.ToString()' is security transparent, but is a member of a security critical type.
Source=Mono.CSharp
TypeName=Mono.CSharp.Location.ToString()
StackTrace:
at Mono.CSharp.Evaluator..cctor()
InnerException:
A google confirms one other person asking this question but no answer. I tried to start reading the microsoft article on security transparent code but got confused quite quickly. Would someone be able to suggest a quick workaround to allow me to use this? And possibly summarise the security implications, if any, to me (in the context of my situation - in the future I hope to package it with a thick client application, to be used both internally and by end-users)
It has worked under .NET since April of last year.
Small point but I notice you are missing a semi-colon in your expression for sum.
int sum = (int)Evaluator.Evaluate("1+2;");
I only have Mono 2.11 (from git) at the moment and they have changed to using a multi-instance version of the compiler instead of the static version. So, my code looks a little different:
using System;
using Mono.CSharp;
namespace REPLtest
{
class MainClass
{
public static void Main (string[] args)
{
var r = new Report (new ConsoleReportPrinter ());
var cmd = new CommandLineParser (r);
var settings = cmd.ParseArguments (args);
if (settings == null || r.Errors > 0)
Environment.Exit (1);
var evaluator = new Evaluator (settings, r);
evaluator.Run("using System;");
int sum = (int) evaluator.Evaluate("1+2;");
Console.WriteLine ("The sum of 1 + 2 is {0}", sum);
}
}
}
EDIT: I guess I should confirm that I did in fact successfully execute this on .NET 4 (using Visual C# Express 2010 on Windows XP)
EDIT AGAIN: If you have Visual Studio, you can download the latest version of Mono.CSharp and compile it yourself. There is a .sln (solution file) included with the source so you can build it on Windows without Mono. The resulting assembly would run the code above. Miguel has a post explaining the new Mono.CSharp here.
FINAL EDIT: I uploaded the compiled Mono.CSharp.dll assembly that I actually used here. Include it as a reference to compile the code above.
It looks like this is a bug in Mono.
.NET 4 abandoned Code Access Security but kept the concept of Security Transparent Code. In a nutshell, low-level code that does stuff, like call unmanaged code, must be "security critical". Application level code is marked "transparent". "Transparent" code cannot call into "security critical" code.
It sounds like Mono.CSharp.Location.ToString() needs to be marked with the [SecuritySafeCritical] attribute if you want the Mono 2.10 code to work with .NET 4. Maybe even better would be marking all of Mono.CSharp as SecuritySafeCritical.
http://msdn.microsoft.com/en-us/library/system.security.securitycriticalattribute.aspx
PS. Sorry to have multiple answers for one question. After I realized that 2.11 would work, I became more curious about what the error with 2.10 meant. I cannot really combine this answer with the others.
I decided I should have kept the code more like the question but I did not want to overwrite my previous answer:
The code below works with version 2.11 of Mono.CSharp (available here including a solution file for building with Visual Studio/.NET). It was tested with .NET 4 on Windows XP. I do not have access to Mono 2.10 at the moment.
[TestFixture]
class Class1
{
private Evaluator evaluator;
public Class1()
{
var report = new Report(new ConsoleReportPrinter());
evaluator = new Evaluator(new CompilerSettings(), report);
}
[Test]
public void EXPR()
{
evaluator.Run("using System;");
int sum = (int)evaluator.Evaluate("1+2;");
}
}
EDIT: I uploaded the Mono.CSharp.dll assembly that I actually used here. Include it as a reference to compile the code above.

Categories