Compiling and running C # and Blazor inside

 3r33333. 3r3-31.
Introduction 3r33333.
 3r33333.
Compiling and running C # and Blazor inside
 3r33333.
If you are a web developer and are developing for a browser, then you are definitely familiar with JS, which can be executed inside a browser. There is an opinion that JS is not very suitable for complex calculations and algorithms. And although in recent years JS has made a big breakthrough in performance and breadth of use, many programmers continue to dream of launching a system language inside the browser. In the near future, the game may change thanks to WebAssembly.
 3r33333.
Microsoft is not standing still and is actively trying to port .NET to WebAssembly. As one of the results, we received a new framework for customer development - Blazor. It is not quite clear yet whether Blazor can be faster than modern JS frameworks like React, Angular, Vue due to WebAssembly. But it definitely has a big advantage - development in C #, as well as the whole .NET Core world can be used inside the application.
 3r33333.
Compiling and running C # in Blazor
 3r33333.
The process of compiling and executing such a complex language as C # is a complex and time-consuming task. 3r33354. Is it possible to compile and execute C # inside a browser? 3r33333. - It depends on the capabilities of the technology (or rather, the core). However, Microsoft, as it turned out, had already prepared everything for us.
 3r33333.
First, create a Blazor app
 3r33333.

 3r33333.
After that, you need to install Nuget - a package for analyzing and compiling C #.
 3r33333.
Install-Package Microsoft.CodeAnalysis.CSharp
 3r33333.
Prepare the start page.
 3r33333.
@page "/"
@inject CompileService service
3r33333.

Compile and Run C # in Browser

3r33333. 3r33333. 3r3633. 3r33333. 3r3365. 3r33333.
C # Code
3r33333.
3r371. 3r33333. 3r33385. 3r33333.
3r33333.
3r33333.
3r33333.
@ResultText
3r33333. 3r33385. 3r33333. 3r33385. 3r33333.
3r33333.
3r33333.
@CompileText
3r33333. 3r33385. 3r33333. 3r33385. 3r33333. 3r33385. 3r33333. 3r33333. @functions
{
string CsCode {get; set;}
string ResultText {get; set;}
string CompileText {get; set;}
3r33333. public async Task Run ()
{
ResultText = await service.CompileAndRun (CsCode); 3r33333. CompileText = string.Join ("rn", service.CompileLog); 3r33333. this.StateHasChanged (); 3r33333.}
}

 3r33333.
First you need to parse the string into an abstract syntax tree. Since in the next step we will be compiling Blazor components, we need the latest ( LanguageVersion.Latest ) Version of the language. For this, Roslyn for C # has a method:
 3r33333.
    SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText (code, new CSharpParseOptions (LanguageVersion.Latest)); 3r33333.  

 3r33333.

Already at this stage, you can detect gross compilation errors by reading the parser diagnostics.


 3r33333.
    foreach (var diagnostic in syntaxTree.GetDiagnostics ())
{
CompileLog.Add (diagnostic.ToString ()); 3r33333.}

 3r33333.

Next we compile Assembly into binary stream.


 3r33333.
    CSharpCompilation compilation = CSharpCompilation.Create ("CompileBlazorInBlazor.Demo", new[]{SyntaxTree},
References, new CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary)); 3r33333. 3r33333. using (MemoryStream stream = new MemoryStream ())
{
EmitResult result = compilation.Emit (stream); 3r33333.}
3r33333.

 3r33333.

Please note that you need to get references - list of metadata of connected libraries. But read these files along the path Assembly.Location It did not work, because there is no file system in the browser. Perhaps there is a more effective way to solve this problem, but the goal of this article is a conceptual opportunity, so we download these libraries again via Http and do it only when we first start compiling.


 3r33333.
    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies ())
{
references.Add (
MetadataReference.CreateFromStream (
await this._http.GetStreamAsync ("/_ framework /_bin /" + assembly.Location)))); 3r33333.}
3r33333.

 3r33333.

From 3r33354. EmitResult you can find out if the compilation was successful, as well as get diagnostic errors.
 3r33333. Now you need to download Assembly in the current AppDomain and execute the compiled code. Unfortunately, inside the browser it is not possible to create multiple AppDomain therefore it is safe to load and unload Assembly will not work.


 3r33333.
    Assembly assemby = AppDomain.CurrentDomain.Load (stream.ToArray ()); 3r33333. var type = assemby.GetExportedTypes (). FirstOrDefault (); 3r33333. var methodInfo = type.GetMethod ("Run"); 3r33333. var instance = Activator.CreateInstance (type); 3r33333. return (string) methodInfo.Invoke (instance, new object[]{"my UserName", 12}); 3r33333. 3r33333.  

 3r33333.


 3r33333.

At this stage, we compiled and executed C # code directly in the browser. A program can consist of several files and use other .NET libraries. Is not that great? Now we go further.


 3r33333.

Compiling and running the Blazor component in a browser. 3r33333.
 3r33333.

Blazor components are modified Razor patterns. Therefore, to compile the Blazor component, you need to deploy a whole environment for compiling Razor templates and set up extensions for Blazor. You need to install the package. Microsoft.AspNetCore.Blazor.Build from nuget. However, adding it to our Blazor project will not work, because then the linker will not be able to compile the project. Therefore, you need to download it, and then manually add 3 libraries.
 3r33333.
microsoft.aspnetcore.blazor.build

+ 0 -

Add comment