Dynamic Code Compilation in .Net Core 2.1 - c#

Has anyone managed to find a workaround/way to dynamically compile a file, or files, or text, into a .dll in .Net Core (2.1)?
var csProvider = CodeDomProvider.CreateProvider("CSharp");
CompilerResults compilerResults = csProvider.CompileAssemblyFromFile(options, files);
results in a PlatformNotSupportedException and it seems CodeDom is only of very limited use in .Net Core. See similar complaint and compare view of System.CodeDom.Compiler in .Net Core 2.1 vs .Net Framework 4.7.2.
We need to be able to write and dynamically compile custom code on-site. I have a way of dynamically loading any resultant .dll, but I just need to be able to get that .dll in the first place.
The only workaround I can see at the moment is to create a .Net Framework api/service to do this. Is the only other solution here to give up on .Net Core and go to .Net Framework?
Note: I wanted to do this dynamically within the code base. So the solution for "Is it possible to compile a single C# code file with .net core Roslyn compiler?" is not relevant as it states: "To invoke Roslyn compiler directly it is necessary to use command line driver" which would have set me on completely the wrong path. However "How to compile a C# file with Roslyn programmatically?" would provide the solution if I'd known that that is what I was looking to do.
The link provided by #Sami Kahmonem to Joel Martinez' solution in .Net Core 1 was what I used to solve this problem.

There are two options for you.
Use the Roslyn Scripting API (Microsoft.CodeAnalysis.CSharp.Scripting). This is pretty easy and surprisingly fast. Also you do not write any binaries to the file system.
Use the full compiler to create a DLL and load it. I would not recommend doing this if possible.
For detailed explanations you should look at this question: Compiling and Running code at runtime in .Net Core 1.0 (you do not need to create a NuGet.config or anything like this)

Related

can you compile a c# script without a csproj file in dotnet 5 and later

I mean like in c++ you can do cl.exe main.cpp
I don't have really any reason to do that, just curious
Assuming by "script" you mean "normal C# source file" then yes, absolutely, if csc is available to you:
Program.cs:
using System;
Console.WriteLine("Hello world");
Compile:
csc Program.cs
Run:
./Program.exe
Now, decompiling that, it looks like it's targeting .NET Framework rather than .NET Core by default, but I'd expect it to be feasible to change that if you really want to, by specifying a custom response file. It does make the latest C# features available to you, but if you use C# features that are only supported on later versions of .NET (e.g. default interface implementations) then I suspect you'd have to explicitly specify the appropriate standard libraries rather than using the default .NET Framework ones.
If csc isn't available to you as an executable, the DLL may still be available in the .NET SDK directory, under Roslyn/bincore.
For example, on my WSL2 Ubuntu installation, just trying to run csc fails, but the command below definitely invokes csc:
dotnet /usr/share/dotnet/sdk/6.0.202/Roslyn/bincore/csc.dll
The bad news is that trying to use that to just compile a standalone program requires providing library references etc - that's probably more hassle than it's worth.
No - but, for what you may be looking for, the dotnet new console command generates a default csproj that runs the Program.cs file that is also generated.
With the new(ish) top level statement files, you can just insert a few usings and your script code, and just use dotnet run
If you're using an IDE, it'll run all the dotnet commands for you though
Yes C# has a Scripting concept(.csx). It also has a REPL (csi.exe)
References : https://learn.microsoft.com/en-us/archive/msdn-magazine/2016/january/essential-net-csharp-scripting

What does <ImportWindowsDesktopTargets> do in a try-convert generated *.csproj?

I have used the try-convert tool to convert my projects from .NET Framework to .NET 5.0
When inspecting the converted *.csproj files for projects that are targeting .net50-windows I noticed the element:
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
I am curious to understand what it does?
Is this essential or another example of something that try-convert puts in the *.csproj but is not really required to be present in the *.csproj any more?
Thanks.
The same happened when I used upgrade-assistant to do the upgrade and I also
wondered what the ImportWindowsDesktopTargets means and whether I needed it. I could find no official documentation for it, only this discussion. According to the question in the discussion, adding an ImportWindowsDesktopTargets property is one way to allow multitargetting using the TargetFramworks property, like this:
<TargetFrameworks>net472;net5.0-windows</TargetFrameworks>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
As my project does not need to target multiple frameworks, just net5.0-windows, and as I have other projects, both Windows Forms and WPF, that target only net5.0-windows and work fine without ImportWindowsDesktopTargets, I removed ImportWindowsDesktopTargets from the converted project with no problems.
According to the proposed answer in the linked discussion, even if you do want to target multiple frameworks, there may be a better way to do it.
This is for pre-Net5.0 behavior to force importing WindowsDesktop Targets.
If you are using Net 5.0 or a newer version, Microsoft.NET.Sdk.WindowsDesktop will always be imported by the SDK, so you may remove it.

EF6 library migration to .net standard 2.1 - EDMX resources not included in .dll

I've got a library that was written in full .Net which I've got to move to .Net Standard 2.1 - I've validated my process on smaller projects and from a coding and .csproj perspective it's all fine.
The problem: This library wraps around a 3rd party SQL database using EF6 so I have to stick to the Database-First model and with that I need to supply metadata to in my connection string to show the .csdl, .msl and .ssdl resources.
The project is multi-targeting .Net 4.7.2 and .Net Standard 2.1 and comparing the output in dotPeek I can clearly see those resources are missing from the new output:
What I tried:
Double checked that the "Metadata Artifact Processing" is set to "Embed in Output Assembly".
Validated that the .Net 4.7.2 output works as intended.
I've tried specifying resources in the connection string like:
metadata=res://*/;provider=...
But that only throws a different error:
Argument 'xmlReader' is not valid. A minimum of one .ssdl artifact must be supplied
Any ideas will be most appreciated, many thanks.
In a bizarre fashion I have resolved this by swapping the target framework around...
From:
<TargetFrameworks>net472;netstandard2.1</TargetFrameworks>
To:
<TargetFrameworks>netstandard2.1;net472</TargetFrameworks>
And it just started including the resources correctly... strange but it works!

How to tell if code is written for regular .NET or .NET Core?

I work with a code base that contains some code in regular .NET and some code in .NET Core. When I open an individual .cs file, I'm not always sure whether the file was meant to be compiled with regular .NET or .NET Core. Obviously, there's a lot of overlap between both frameworks -- and a lot of code can be run unmodified in both frameworks.
So my question is, what are some easy ways to determine whether a .cs file is intended to be compiled for regular .NET or .NET Core?
(I imagine that looking for certain usings that only exist in one framework or the other is probably the biggest telltale sign. If that is indeed the way to determine this, is there a web page which lists which usings are exclusive to regular .NET vs. .NET Core?)
Your best bet is to look at the .csproj file.
Look for either the <TargetFramework> or the <TargetFrameworks> element. It will have entries such as net461. You can cross reference with the chart here:
https://learn.microsoft.com/en-us/dotnet/standard/frameworks
Microsoft has a Portability Analyzer that will tell you if your code will run on various platforms and what kind of changes are required, but the only way I know to tell what platform particular code was written for is to check the project properties or makefile.
You could also use an if preprocessor directive such as something like this:
public class MyClass
{
static void Main()
{
#if (NETCOREAPP1_0 || NETCOREAPP1_1 || NETCOREAPP2_0 || NETCOREAPP2_1)
<some code>
#else
<some code>
#endif
}
}
I should add that this is a method to use going forward especially with shared code used between NetFramework and Core.

Implementing C# compiler (Online) like compilr.com

Im working on creating a feature in a website, where people cah write C# code in the input box , and it can be compiled and results emitted.
Any resources or suggestions as to how to start with this.
The .Net framework has built in runtime compilers. They are in the System.CodeDom.Compiler namespace.
The other thing to consider is when you are compiling the code what assemblies you link in. If you link in an assembly the code you compile will have full access to that assembly and it will be compiled and running on your server.
Code compiled should be done in a sandbox. You can interface with the compiler through the command line.
http://msdn.microsoft.com/en-us/library/1700bbwd(v=vs.71).aspx
I'm using Microsoft.Build and Microsoft.Build.Framework in my online .Net IDE, Chpokk. Soon, Roslyn will be the way to go (I'm currently using it for Intellisense).

Categories