引用 Newtonsoft.Json.dll 时,在运行时在单声道下编译 C# 代码失败
Compiling C# code at runtime under mono fails when referencing Newtonsoft.Json.dll
我们的软件是用C#
运行.Net-Framework 4.7.2
编写的。我们的用户可以使用我们软件中内置的脚本编辑器,使用 C# 编写自己的用户脚本。为实现这一点,我们正在使用 .Net 组件 CodeDomProvider
。为了能够以简单的方式使用 JSON,我们希望在我们的用户脚本中引用 Newtonsoft.Json.dll
。这是通过添加对 CodeDomProvider 的 CompilerParameters 的引用来完成的。 Newtonsoft.Json 通过使用最新的 Newtonsoft.Json NuGet
包 (12.0.3) 添加到我的应用程序中。
这里是此设置的最小示例:
using System;
using System.CodeDom.Compiler;
using System.IO;
namespace ScriptingUnix
{
class Program
{
static void Main(string[] args)
{
try
{
string output;
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
output = "/tmp/MyUnixTest.dll";
}
else
{
output = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyUnixTest.dll");
}
CompilerParameters parameters = new CompilerParameters
{
GenerateInMemory = false,
IncludeDebugInformation = true,
OutputAssembly = output
};
using (CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp"))
{
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("Newtonsoft.Json.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource
(
parameters,
"using System;\nusing Newtonsoft.Json.Serialization;\nusing Newtonsoft.Json.Linq;\n class Program\r\n{\r\n static void Main(string[] args)\r\n {\r\n \r\n }\r\n}"
);
foreach (CompilerError compilerError in results.Errors)
{
Console.WriteLine(compilerError);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
}
}
此设置在 Windows 上的 .Net Framework 下运行良好。问题是,我们还在 (Arch)-Linux (Linux 4.19.80-1-ARCH armv7l,Mono JIT 编译器版本 6.0 上提供我们的软件版本 运行 Mono .0(makepkg/6256b82d62f 2019 年 9 月 25 日星期三 05:04:08 AM UTC),其中 运行 与单声道相同的代码导致 error CS0006: Metadata file Newtonsoft.Json.dll could not be found
。
我已经尝试将以下内容添加到我的应用程序的 app.conf 中,但这没有帮助。同样重新安装 NuGet
软件包也没有帮助。将 Newtonsoft.Json.dll
添加到 GAC 不起作用(Failure adding assembly Newtonsoft.Json.dll to the cache: The file specified is not a valid assembly.
失败)。在尝试使用 app.conf 时,我发现错误消息已更改为 error CS0009: Metadata file /opt/Newtonsoft.Json.dll does not contain valid metadata: Metadata file /opt/Newtonsoft.Json.dll does not contain valid metadata
。这就是为什么我猜他找到了 dll 但需要额外的有效元数据。我想到了某种 dll.conf.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
有人知道如何让它工作吗?
您的代码示例在 .NET 4.7 上运行良好,但由于您是 运行 Mono,这里有一些适合您的解决方案:
编译器需要知道从哪里获得这个文件。
如果您说您需要引用 System.dll
- 编译器可能会尝试在 GAC 中找到它(并且确实找到了它)。
当您引用 Newtonsoft.Json.dll
之类的未知库时,它会尝试搜索 GAC 但会失败。然后它可能试图在工作目录中找到它,etc..
解决方案 #1:
尝试设置您的库的完整路径;
解决方案 #2:
在 GAC 中尝试 register Newtonsoft.Json.dll
;
解决方案 #3:
试试 .NET Core!太棒了,跨平台,3.1版本现在开源了WinForms和WPF!
我知道将代码迁移到 .NET Core 3 需要时间,但仍然值得。
你有两种可能:
使用 github 的最新 Mono (6.6)。如果包不可用,请编译它。
将 Newtonsoft.Json 降级到版本 11.0。必要时使用绑定重定向。
我们的软件是用C#
运行.Net-Framework 4.7.2
编写的。我们的用户可以使用我们软件中内置的脚本编辑器,使用 C# 编写自己的用户脚本。为实现这一点,我们正在使用 .Net 组件 CodeDomProvider
。为了能够以简单的方式使用 JSON,我们希望在我们的用户脚本中引用 Newtonsoft.Json.dll
。这是通过添加对 CodeDomProvider 的 CompilerParameters 的引用来完成的。 Newtonsoft.Json 通过使用最新的 Newtonsoft.Json NuGet
包 (12.0.3) 添加到我的应用程序中。
这里是此设置的最小示例:
using System;
using System.CodeDom.Compiler;
using System.IO;
namespace ScriptingUnix
{
class Program
{
static void Main(string[] args)
{
try
{
string output;
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
output = "/tmp/MyUnixTest.dll";
}
else
{
output = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyUnixTest.dll");
}
CompilerParameters parameters = new CompilerParameters
{
GenerateInMemory = false,
IncludeDebugInformation = true,
OutputAssembly = output
};
using (CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp"))
{
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("Newtonsoft.Json.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource
(
parameters,
"using System;\nusing Newtonsoft.Json.Serialization;\nusing Newtonsoft.Json.Linq;\n class Program\r\n{\r\n static void Main(string[] args)\r\n {\r\n \r\n }\r\n}"
);
foreach (CompilerError compilerError in results.Errors)
{
Console.WriteLine(compilerError);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
}
}
此设置在 Windows 上的 .Net Framework 下运行良好。问题是,我们还在 (Arch)-Linux (Linux 4.19.80-1-ARCH armv7l,Mono JIT 编译器版本 6.0 上提供我们的软件版本 运行 Mono .0(makepkg/6256b82d62f 2019 年 9 月 25 日星期三 05:04:08 AM UTC),其中 运行 与单声道相同的代码导致 error CS0006: Metadata file Newtonsoft.Json.dll could not be found
。
我已经尝试将以下内容添加到我的应用程序的 app.conf 中,但这没有帮助。同样重新安装 NuGet
软件包也没有帮助。将 Newtonsoft.Json.dll
添加到 GAC 不起作用(Failure adding assembly Newtonsoft.Json.dll to the cache: The file specified is not a valid assembly.
失败)。在尝试使用 app.conf 时,我发现错误消息已更改为 error CS0009: Metadata file /opt/Newtonsoft.Json.dll does not contain valid metadata: Metadata file /opt/Newtonsoft.Json.dll does not contain valid metadata
。这就是为什么我猜他找到了 dll 但需要额外的有效元数据。我想到了某种 dll.conf.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
有人知道如何让它工作吗?
您的代码示例在 .NET 4.7 上运行良好,但由于您是 运行 Mono,这里有一些适合您的解决方案:
编译器需要知道从哪里获得这个文件。
如果您说您需要引用 System.dll
- 编译器可能会尝试在 GAC 中找到它(并且确实找到了它)。
当您引用 Newtonsoft.Json.dll
之类的未知库时,它会尝试搜索 GAC 但会失败。然后它可能试图在工作目录中找到它,etc..
解决方案 #1:
尝试设置您的库的完整路径;
解决方案 #2:
在 GAC 中尝试 register Newtonsoft.Json.dll
;
解决方案 #3:
试试 .NET Core!太棒了,跨平台,3.1版本现在开源了WinForms和WPF!
我知道将代码迁移到 .NET Core 3 需要时间,但仍然值得。
你有两种可能:
使用 github 的最新 Mono (6.6)。如果包不可用,请编译它。
将 Newtonsoft.Json 降级到版本 11.0。必要时使用绑定重定向。