catalogue
Compile c# text as dll in real time
1. Add the PreserveCompilationContext configuration
3. Get the compilation reference dll by using {DependencyContext}
Introduction to Rosyln
Rosyln1{yes NET Core and NET 4.6 +, which is also used by IDE Visual Studio to compile code. Based on the idea that the compiler is also a service, Microsoft developers separate it and maintain it open source. See footnote 2 for the open source address.
In the workflow engine or rule engine, it is sometimes necessary to calculate expressions. In the past, we usually used Antlr 3 to build complex parser code according to special syntax (grammar). It's like an enhanced regular expression for language parsing. Of course, you can also use the popular interpretive language engine to do this. You can refer to my previous article, an introduction to Javascript engine.
There is also a similar C# compiler scripting engine C# Scripting API 4 under Rosyln to complete the following expression evaluation.
Installation package * Microsoft CodeAnalysis. CSharp. Scripting*
int result = await CSharpScript.EvaluateAsync<int>("1 + 2");
Compile c# text as dll in real time
Latest package Microsoft CodeAnalysis. CSharp has been supported net core, so net core has no problem compiling c# strings. Follow the steps below:
1. Add the PreserveCompilationContext configuration
Edit your csproj project file and add the following configuration
<PropertyGroup> <PreserveCompilationContext>true</PreserveCompilationContext> </PropertyGroup>
2. Reference package
Edit your csproj project file and add the following configuration
<ItemGroup> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.11.0-beta1-final" /> <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" /> </ItemGroup>
3. Get the compilation reference dll by using {DependencyContext}
MetadataReference[] _ref = DependencyContext.Default.CompileLibraries .First(cl => cl.Name == "Microsoft.NETCore.App") .ResolveReferencePaths() .Select(asm => MetadataReference.CreateFromFile(asm)) .ToArray();
Complete example
MetadataReference[] _ref = DependencyContext.Default.CompileLibraries .First(cl => cl.Name == "Microsoft.NETCore.App") .ResolveReferencePaths() .Select(asm => MetadataReference.CreateFromFile(asm)) .ToArray(); string testClass = @"using System; namespace test{ public class tes { public string unescape(string Text) { return Uri.UnescapeDataString(Text); } } }"; var compilation = CSharpCompilation.Create(Guid.NewGuid().ToString() + ".dll") .WithOptions(new CSharpCompilationOptions( Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary, usings: null, optimizationLevel: OptimizationLevel.Debug, // TODO checkOverflow: false, // TODO allowUnsafe: true, // TODO platform: Platform.AnyCpu, warningLevel: 4, xmlReferenceResolver: null // don't support XML file references in interactive (permissions & doc comment includes) )) .AddReferences(_ref ) ) .AddSyntaxTrees(CSharpSyntaxTree.ParseText(testClass)); var eResult = compilation.Emit("test.dll");
Reference test library
Follow the steps of the above example to successfully generate test DLL file, I reference and test whether it is executable.
var t = new test.tes(); var txt = t.unescape("abcdefg");
Everything is OK, Congratulations! You've done it perfectly net core c#.
summary
The difficulty lies in the introduction of DependencyContext. Many people are stuck in this step because net target will be selected by default when compiling net framework library, then your dll can be generated, but it can't be introduced into net core project!
Footnotes
-
https://github.com/dotnet/roslyn/wiki ↩︎
-
https://github.com/dotnet/roslyn ↩︎
-
https://www.antlr.org/download.html ↩︎
-
https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples ↩︎