Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with Microsoft.CodeDom.Providers.DotNetCompilerPlatform

Tags:

c#

.net

.net-core

I have an application that does some dynamic code generation and compilation and has been working well with System.CodeDom and Microsoft.CSharp. I am porting this to .net Core 3.1, and so have upgraded to use Microsoft.CodeDom.Providers.DotNetCompilerPlatform. However, I have run into problems that may be related. The first is that Visual Studio displays the following message in the Packages section of References:

Package 'Microsoft.CodeDom.Providers.DotNetCompilerPlatform 2.0.1' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETCoreApp,Version=v3.1'. This package may not be fully compatible with your project.

Secondly (and this may be related), when the application hits this line:

CSharpCodeProvider codeProvider = new CSharpCodeProvider();

Then the following exception is thrown:

The type initializer for 'Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CompilationSettingsHelper' threw an exception.

I'd be grateful for any help!

like image 618
user304582 Avatar asked Sep 21 '26 17:09

user304582


1 Answers

In the hopes that this may help others trying to solve the same problem, here's what I ended up with using the Microsoft.CodeAnalysis.CSharp package:

Assembly assembly = null;
string[] sourceStringArray = null;// set this to hold the arrary of source strings
List<SyntaxTree> syntaxTreeList = new List<SyntaxTree>();
foreach (string sourceString in sourceStringArray)
{
    SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceString);
    syntaxTreeList.Add(syntaxTree);
}

string assemblyName = Path.GetRandomFileName();
AppDomain currentDomain = AppDomain.CurrentDomain;
List<MetadataReference> metadataReferenceList = new List<MetadataReference>();
Assembly[] assemblyArray = currentDomain.GetAssemblies();
foreach (Assembly domainAssembly in assemblyArray)
{
    try
    {
        AssemblyMetadata assemblyMetadata = AssemblyMetadata.CreateFromFile(domainAssembly.Location);
        MetadataReference metadataReference = assemblyMetadata.GetReference();
        metadataReferenceList.Add(metadataReference);
    }
    catch (Exception e)
    {
        Log.DebugFormat("failed to get MetadataReference {0}", e.Message);
    }
}

CSharpCompilation compilation = CSharpCompilation.Create(
    assemblyName,
    syntaxTrees: syntaxTreeList,
    references: metadataReferenceList,
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
    EmitResult result = compilation.Emit(ms);
    if (!result.Success)
    {
        IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error);
        foreach (Diagnostic diagnostic in failures)
        {
            /* Process failures */
        }
    }
    else
    {
        ms.Seek(0, SeekOrigin.Begin);
        assembly = Assembly.Load(ms.ToArray());
    }
}

I am sure that this is not optimal (and would welcome suggestions to improve!).

like image 141
user304582 Avatar answered Sep 23 '26 09:09

user304582



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!