【问题标题】:Not getting a namespace/reference in CSharpCompilation .net Core在 CSharpCompilation .net Core 中没有获得命名空间/引用
【发布时间】:2020-10-19 21:39:36
【问题描述】:

我有一个使用一些动态编译代码的项目,我正在从 .net 框架升级到 .net core 3.1。

我无法获得包含 newtonsoft.json.dll 的简单测试用例,并收到错误“找不到类型或命名空间名称 'Newtonsoft'。我第一次尝试添加库时遇到了类似的问题,但是通过使用当前加载的程序集 (Can't include Newtonsoft JSON in CSharpCodeProvider script) 克服了它。使用“核心”我不会收到有关库的错误,但它不知道类型,就像它没有被加载一样。

我尝试使用项目库(已注释掉)并直接指定它们,但有同样的问题。要重新创建,请创建一个名为“TestScript”的新 .netCore 3.1 控制台应用程序并安装 nuget 包“Microsoft.CodeAnalysis.CSharp.Scripting”v 3.7.0、“Newtonsoft.Json”v12.0.3 并使用以下代码。

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System.Diagnostics;
using Newtonsoft.Json.Linq;

namespace TestScript
{  
  class Program
  {
    public static void Example1()
    {
      var assemblyName = "UserScript";
      var code = @"namespace UserScript
                { 
                  using System;
                  using System.IO;
                  using System.Collections.Generic;
                  using Newtonsoft.Json.Linq;
                  public class RunScript
                  {
                    private const int x = 99;
                    public int Eval()
                    {
                      JObject j = new JObject();
                      return x; 
                    }
                  }
                }";

      SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
      var references = new List<MetadataReference>();
      //Load project libraries
      //var assemblies = AppDomain.CurrentDomain
      //                .GetAssemblies()
      //                .Where(a => !a.IsDynamic)
      //                .Select(a => a.Location);
      //foreach (var item in assemblies)
      //{
      //  if (!item.Contains("xunit"))
      //    references.Add(MetadataReference.CreateFromFile(item));
      //}

      //or specify the libraries to load.

      var coreDir = Directory.GetParent(typeof(Enumerable).GetTypeInfo().Assembly.Location);
      var exeDir = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
      references.Add(MetadataReference.CreateFromFile(typeof(Object).GetTypeInfo().Assembly.Location));
      references.Add(MetadataReference.CreateFromFile(typeof(Uri).GetTypeInfo().Assembly.Location));
      references.Add(MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "mscorlib.dll"));
      references.Add(MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "System.Runtime.dll"));
      if (File.Exists(exeDir + "\\Newtonsoft.Json.dll"))
        references.Add(MetadataReference.CreateFromFile(exeDir + "\\Newtonsoft.Json.dll"));
      else
        throw new Exception("Missing newtonsoft DLL");


      CSharpCompilation compilation = CSharpCompilation.Create(
          assemblyName,
          new[] { syntaxTree },
          new MetadataReference[]
          {
        MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
          },
          new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

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

        if (result.Success)
        {
          memoryStream.Seek(0, SeekOrigin.Begin);
          Assembly assembly = Assembly.Load(memoryStream.ToArray());

          Type testClassType = assembly.GetType("TestNamespace.TestClass");
          var addResult = (int)testClassType.GetMethod("Add").Invoke(null, new object[] { 3, 4 });
          Console.WriteLine(addResult);
        }
        else
        {
          Console.WriteLine("Failed to compile");
          for (var i = 0; i < result.Diagnostics.Length; i++)
          {
            Console.WriteLine(result.Diagnostics[i].ToString());
          }
        }
      }
    }
    static void Main(string[] args)
    {
      JObject j = null; //to make sure newtonsoft is included if loading current projects libraries

      Example1();
    }
  }
}

【问题讨论】:

    标签: c# .net-core roslyn roslyn-code-analysis


    【解决方案1】:

    如果您没有忘记使用您建立的references 列表,您的代码应该可以正常工作。

    查看 .NET Fiddle (link) 上的测试代码 - 我在那里使用了 AppDomain 方法(您注释掉的方法)。

    CSharpCompilation compilation = CSharpCompilation.Create(
        assemblyName,
        new[] { syntaxTree },
        references, //<-- you're missing this
        new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
    

    此外,您的调用实际上并未调用正确的类和方法,我想您会在解决编译问题后发现。

    // Non-existent Type and Method...
    Type testClassType = assembly.GetType("TestNamespace.TestClass");
    var addResult = (int)testClassType.GetMethod("Add").Invoke(null, new object[] { 3, 4 });
    

    编辑:这是完整的工作代码,以防 Fiddle 被删除:

    public static void Main(string[] args)
    {
        var j = new JObject(); // ensure assembly is available
        Example1();
    }
    
    public static void Example1()
    {
        var assemblyName = "UserScript";
        var code = @"namespace UserScript { 
                      using Newtonsoft.Json;
                      public class RunScript {
                       public static string Eval() {
                        return JsonConvert.SerializeObject(new int[] {1,2,3,4});
                       }
                      }
                    }";
    
        SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
        
        //Load project libraries
        var references = AppDomain.CurrentDomain
            .GetAssemblies()
            .Where(a => !a.IsDynamic)
            .Select(a => a.Location)
            .Where(s => !string.IsNullOrEmpty(s))
            .Where(s => !s.Contains("xunit"))
            .Select(s => MetadataReference.CreateFromFile(s))
            .ToList()
            ;
    
        CSharpCompilation compilation = CSharpCompilation.Create(
            assemblyName,
            new[] { syntaxTree },
            references, //<-- you're missing this
            new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
    
        using (var memoryStream = new MemoryStream())
        {
            var result = compilation.Emit(memoryStream);
    
            if (result.Success)
            {
                memoryStream.Seek(0, SeekOrigin.Begin);
                Assembly assembly = Assembly.Load(memoryStream.ToArray());
    
                var testClassType = assembly.GetType("UserScript.RunScript");
                var invokeResult = (string)testClassType.GetMethod("Eval").Invoke(null, null);
                Console.WriteLine(invokeResult);
            }
            else
            {
                Console.WriteLine("Failed to compile");
                foreach (var diag in result.Diagnostics)
                    Console.WriteLine(diag);
            }
        }
    }
    

    【讨论】:

    • 现在我觉得有点尴尬。我知道我在某一时刻改变了这一点,但我一定是以某种方式解除了它。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    相关资源
    最近更新 更多