简体   繁体   中英

Microsoft.CodeAnalysis: Error compiling dynamic code with Newtonsoft JObject

I'm having a strange problem that I can't fix. I have been compiling dynamic assemblies successfully for the most part but have come up with a strange problem compiling the following line:

return new JObject().Properties().ElementAt(0).Value();

with the error:

System.ApplicationException: 'Error creating dynamic code assembly 'IEnumerable<JProperty>' does not contain a definition for 'ElementAt' and no accessible extension method 'ElementAt' accepting a first argument of type 'IEnumerable<JProperty>' could be found (are you missing a using directive or an assembly reference?) '

The emitted text output works fine when created as a real class in the project but not when in a dynamic assembly. The project is an asp.net core 2.2 project and it references an assembly which creates the dynamic assemblies.

Here is the code that creates the assembly:

public static class Class2
{
    public static Assembly GenerateAssenbly()
    {

        //generate the code
        StringBuilder sb = new StringBuilder("");
        sb.AppendLine("using System;");
        sb.AppendLine("using System.Linq;");

        sb.AppendLine("using Newtonsoft.Json;");
        sb.AppendLine("using Newtonsoft.Json.Linq;");

        sb.AppendLine("namespace test");
        sb.AppendLine("{");
        sb.AppendLine($"class Parser");
        sb.AppendLine("{");

        sb.AppendLine($"public object test() ");
        sb.AppendLine("{");
        sb.AppendLine("return new JObject().Properties().ElementAt(0).Value<string>();");
        sb.AppendLine("}");

        sb.AppendLine("}"); //class
        sb.AppendLine("}"); //namespace

        SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sb.ToString());

        var runtimeAssemblyDirectory = Path.GetDirectoryName(typeof(object).Assembly.Location);
        string assemblyName = Path.GetRandomFileName();
        MetadataReference[] references = new MetadataReference[]
        {
            MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
            MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location),
            MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "System.Runtime.dll")),
            MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "mscorlib.dll")),
            MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "System.dll")),
            MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "netstandard.dll")),
            MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "System.Core.dll")),

            MetadataReference.CreateFromFile(typeof(JObject).GetTypeInfo().Assembly.Location),
        };

        CSharpCompilation compilation = CSharpCompilation.Create(
            assemblyName,
            syntaxTrees: new[] { syntaxTree },
            references: references,
            options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));


        Debug.Print(sb.ToString()); // copy output to a class to test

        using (var ms = new MemoryStream())
        {
            EmitResult result = compilation.Emit(ms);

            if (!result.Success)
            {
                throw new ApplicationException($"Error creating dynamic code assembly " + GetCompilerResultsErrors(result));
            }
            else
            {
                return Assembly.Load(ms.GetBuffer());
            }
        }
    }

    private static string GetCompilerResultsErrors(EmitResult result)
    {
        StringBuilder sb = new StringBuilder();

        IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
            diagnostic.IsWarningAsError ||
            diagnostic.Severity == DiagnosticSeverity.Error);

        foreach (Diagnostic diagnostic in failures)
        {
            sb.AppendLine(diagnostic.GetMessage());
        }

        return sb.ToString();
    }
}

(the code shown is not intended for working purposes, it is simplified to demonstrate the problem)

Thanks in advance,

solution was to add specific references:

MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "System.Linq.Expressions.dll")),
MetadataReference.CreateFromFile(Path.Combine(runtimeAssemblyDirectory, "System.Linq.dll")),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM