Mercator 10.0 permet la compilation "à la volée" de code C#, notamment dans l'éditeur de code. Par défaut, Mercator utilise les ressources System.CodeDom.Compiler, qui reposent sur le compilateur CSC.exe inclus dans le framework .net. Ce compilateur est toutefois limité à la version 5.0 de C#.
Pour pouvoir utiliser des syntaxes faisant appel à des notations supportées par les versions ultérieures de C#, il faut indiquer à Mercator qu'il doit utiliser le compilateur Roslyn, appelé officiellement ".NET Compiler Platform". Ce compilateur, entièrement écrit sur la plateforme .net elle-même, ne dépend plus d'aucun autre exécutable.
La version du compilateur actuellement implémentée dans Mercator est Roslyn 2.0, dont la release officielle a été faite simultanément à celle de Visual Studio 2017. Il est donc compatible avec C# 7.0.
Dans l'éditeur de code C# de Mercator, le menu contextuel contient un élément permettant d'ajouter une clause de compilation indiquant que la compilation doit être effectuée par Roslyn.
Cette clause de compilation est : // <CompileWithRoslyn />
Ci-dessous quelques exemples de nouvelles syntaxes qui sont compilables dans l'éditeur de code de Mercator. (Cette liste n'est absolument pas exhaustive)
String interpolation
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public void Main()
{
string personne = "Jules";
DateTime naissance = new DateTime(1985, 2, 10);
Dialogs.Stop($"{personne} a {Math.Truncate(DateTime.Now.Subtract(naissance).TotalDays / 365)} ans.");
}
}
}
Null-Conditional Operator
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public void Main()
{
object ox = null;
string s = ox?.ToString() ?? "null";
Dialogs.Stop(s);
}
}
}
Class properties
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public class Person
{
public string First { get; set; } = "Jules";
public string Last { get; set; } = "Dupont";
public string Name => First + " " + Last;
}
public void Main()
{
Person p = new Person();
Dialogs.Stop(p.Name);
}
}
}
Dictionary initializer
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public void Main()
{
var numbers = new Dictionary<int, string> { [7] = "sept", [9] = "neuf", [13] = "treize" };
}
}
}
Out with type
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
using System.Globalization;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public void Main()
{
string s = "2017-03-07";
if (DateTime.TryParseExact(s, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime realaseDate))
Dialogs.Stop("Visual Studio 2017 release date = " + realaseDate.ToShortDateString());
else
Dialogs.Stop("Date incorrecte !");
}
}
}
Is-expressions with patterns
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn /> namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.
IExec {
public void Main()
{
object ox =
"1";
if ((ox
is int i) || ((ox
is string s &&
int.TryParse(s,
out i))))
Dialogs.Stop(
"ox est numérique et vaut " + i);
else Dialogs.Stop(
"ox n'est pas numérique");
}
}
}
Result as ValueTuple
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using MercatorApi;
using MercatorExtensions;
using MercatorUi;
// <CompileWithRoslyn />
namespace MyNameSpace
{
public class Class1 : MercatorUi.Interfaces.IExec
{
public void Main()
{
var premierClient = getNomAdresse();
Dialogs.Stop($"Le premier client est {premierClient.nom.TrimEnd()} et son adresse est {premierClient.adresse.TrimEnd()}");
}
private (string nom, string adresse) getNomAdresse()
{
DataSet ds = Api.Zselect(Globals.RepData, "select top 1 c_nom,c_adresse from CLI");
if (ds?.Tables[0].Rows.Count > 0)
return (ds.Tables[0].Rows[0]["c_nom"].ToString(), ds.Tables[0].Rows[0]["c_adresse"].ToString());
else
return ("?", "?");
}
}
}
Remarque : en mode HTML 5, Mercator compile toujours via Roslyn, parce que le mode sandbox qui prévaut lors de la virtualisation interdit le démarrage d'un autre exécutable (le compilateur CSC.exe).