找不到类型或命名空间名称 ‘Newtonsoft’ (PS 5.1)

huangapple go评论61阅读模式
英文:

The type or namespace name 'Newtonsoft' could not be found (PS 5.1)

问题

我正尝试使用Newtonsoft.Json库

[Reflection.Assembly]::LoadFile('C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json.0.2.201\libs\Newtonsoft.Json.dll')

Add-Type -TypeDefinition @"
using Newtonsoft.Json;

class BigIntegerConverter: JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Org.BouncyCastle.Math.BigInteger));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        System.Numerics.BigInteger big = (System.Numerics.BigInteger)reader.Value;
        return new Org.BouncyCastle.Math.BigInteger(big.ToString());
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value.ToString());
    }
}
"@

并且出现以下错误:

无法找到类型或命名空间名称'Newtonsoft'(您是否缺少使用指令或程序集引用?)

为什么它无法找到Newtonsoft,即使已加载?我可以在PowerShell代码中通过[Newtonsoft.Json.JsonConverter]调用它,但在类型定义中无法使用它!

谢谢!

英文:

I'm trying to use Newtonsoft.Json library:

[Reflection.Assembly]::LoadFile( 'C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json.0.2.201\libs\Newtonsoft.Json.dll' )

Add-Type -TypeDefinition @"
using Newtonsoft.Json;

class BigIntegerConverter: JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Org.BouncyCastle.Math.BigInteger));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        System.Numerics.BigInteger big = (System.Numerics.BigInteger)reader.Value;
        return new Org.BouncyCastle.Math.BigInteger(big.ToString());
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value.ToString());
    }
}
"@

and getting the next error:

> The type or namespace name 'Newtonsoft' could not be found (are you missing a using directive or an assembly reference?)

Why it can't find Newtonsoft tho it loaded? I can call it in PS code via [Newtonsoft.Json.JsonConverter], but not in type definitions!

Thanks!

答案1

得分: 2

<!-- language-all: sh -->

假设在调用脚本之前加载了`Newtonsoft.Json.dll``BouncyCastle.Cryptography.dll`程序集 - 例如,使用`Add-Type -LiteralPath 'C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json.0.2.201\libs\Newtonsoft.Json.dll'` - **您可以使用PowerShell代码定义您的类**,即一个**PowerShell [`class`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Classes)定义**,如下所示:

注意:假设已在运行此脚本之前加载了Newtonsoft.Json.dll和BouncyCastle.Cryptography.dll。

class BigIntegerConverter : Newtonsoft.Json.JsonConverter {
[bool] CanConvert([Type] $objectType){
return $objectType -is [Org.BouncyCastle.Math.BigInteger]
}

[object] ReadJson([Newtonsoft.Json.JsonReader] $reader, [Type] $objectType, [object] $existingValue, [Newtonsoft.Json.JsonSerializer] $serializer) {
    [bigint] $big = $reader.Value
    return [Org.BouncyCastle.Math.BigInteger]::new($big.ToString())
}

WriteJson([Newtonsoft.Json.JsonWriter] $writer, [object] $value, [Newtonsoft.Json.JsonSerializer] $serializer) {
    $writer.WriteRawValue($value.ToString())
}

}


对于在PowerShell中的类定义中必须在手头的脚本之前加载任何类型的要求,可参考此答案中的讨论[这里](https://stackoverflow.com/a/51813639/45375)。

---

至于**您尝试的内容**:

Mathias正确地指出,**通常情况下,您只需要确保将传递给[`Add-Type`](https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Add-Type)的C#代码编译所需的程序集传递给`-ReferencedAssemblies`**。

由于我不清楚的原因,特别是针对`Newtonsoft.Json.dll`,以下代码还需要**在此之前**加载`Newtonsoft.Json.dll`程序集。

* 注意:以下**代码仅适用于Windows PowerShell** - 与上面的PowerShell `class`实现不同,后者在两个版本中均有效。
  * 但是,**可以在PowerShell(Core)7+**中使其工作,需要额外的工作:
     * 使用`NewtonSoft.Json.dll`的*.NET Standard 2.0*实现(所有实现都包含在同一个[`Newtonsoft.Json`](https://www.nuget.org/packages/Newtonsoft.Json) NuGet包中)
        * 在`-ReferencedAssemblies`参数中:
          * 添加`netstandard`
          * 将`System.Numerics`替换为`System.Runtime.Numerics`
        * 然后不需要使用`Add-Type -LiteralPath`预先加载`Newtonsoft.Json.dll`。

  * 或者,使用程序集的*.NET(Core)*实现:
      * 执行与上述相同的步骤,除了添加`netstandard`
      * 将`-IgnoreWarnings -WarningAction Ignore`添加到`Add-Type`调用中,以忽略和消除关于PowerShell的.NET运行时版本与`Newtonsoft.Json.dll`目标版本之间不匹配的警告。

  * 如果*意外*使用了*.NET Framework*实现,您将收到有关找不到核心类型(例如`Object`)的错误,可能是因为它们在.NET Framework程序集中查找。

$jsonAssembly = 'C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json\1.0.2.201\libs\Newtonsoft.Json.dll'

在此处指定BouncyCastle.Cryptography.dll的路径。

$bouncyCastleAssembly = 'C:\path\to\BouncyCastle.Cryptography.dll'

!! 不可解释地,这也是必需的,可能也适用于BouncyCastle.Cryptography.dll

Add-Type -LiteralPath $jsonAssembly

Add-Type -ReferencedAssemblies $jsonAssembly, $bouncyCastleAssembly, System.Numerics -TypeDefinition @'
using System;
using System.Numerics;
using Newtonsoft.Json;

public class BigIntegerConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Org.BouncyCastle.Math.BigInteger));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    BigInteger big = (BigInteger)reader.Value;
    return new Org.BouncyCastle.Math.BigInteger(big.ToString());
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    writer.WriteRawValue(value.ToString());
}

'@


还请注意:

* 添加`using System;`以启用无命名空间引用`Type`类
* 在`-ReferencedAssemblies`中添加`System.Numerics`以及在代码中添加`using System.Numerics;`以允许无命名空间引用`BigInteger`
* 在`BigInterConverter`类定义中添加`public`以确保生成的类是公共的。
英文:

<!-- language-all: sh -->

Assuming you load the Newtonsoft.Json.dll and BouncyCastle.Cryptography.dll assemblies before invoking your script - e.g., with Add-Type -LiteralPath &#39;C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json\1.0.2.201\libs\Newtonsoft.Json.dll&#39; - you can define your class using PowerShell code, i.e. a PowerShell class definition, as follows:

# Note: Assumes that Newtonsoft.Json.dll and BouncyCastle.Cryptography.dll
#       were loaded *before* running this script.
class BigIntegerConverter : Newtonsoft.Json.JsonConverter {
    [bool] CanConvert([Type] $objectType){
        return $objectType -is [Org.BouncyCastle.Math.BigInteger]
    }

    [object] ReadJson([Newtonsoft.Json.JsonReader] $reader, [Type] $objectType, [object] $existingValue, [Newtonsoft.Json.JsonSerializer] $serializer) {
        [bigint] $big = $reader.Value
        return [Org.BouncyCastle.Math.BigInteger]::new($big.ToString())
    }

    WriteJson([Newtonsoft.Json.JsonWriter] $writer, [object] $value, [Newtonsoft.Json.JsonSerializer] $serializer) {
        $writer.WriteRawValue($value.ToString())
    }
}

The - unfortunate - requirement that any types referenced in a PowerShell class have to have been loaded before the script at hand is parsed is discussed in this answer.


As for what you tried:

Mathias is correct in that you normally only need to make sure that the assemblies needed for compiling the C# code passed to Add-Type be passed to -ReferencedAssemblies.

For reasons unknown to me, with Newtonsoft.Json.dll specifically, the code below additionally requires loading the Newtonsoft.Json.dll assembly beforehand too.

  • Note: The code below works in Windows PowerShell only - unlike the PowerShell class implementation above, which works in both editions.
    • However, it can be made to work in PowerShell (Core) 7+, with extra effort:
      • Use the .NET Standard 2.0 implementation of NewtonSoft.Json.dll (all implementations are part of the same Newtonsoft.Json NuGet package)

        • In the -ReferencedAssemblies argument:
          • Add netstandard
          • Replace System.Numerics with System.Runtime.Numerics
        • You then do not load Newtonsoft.Json.dll beforehand with Add-Type -LiteralPath.
      • Alternatively, use the .NET (Core) implementation of the assembly:

        • Follow the same steps as above, except for adding netstandard
        • Add -IgnoreWarnings -WarningAction Ignore to the Add-Type call, to ignore and silence warnings regarding a version mismatch between PowerShell's .NET runtime version and the one targeted by Newtonsoft.Json.dll
      • If you accidentally use a .NET Framework implementation, you'll get errors about not finding core types such as Object, presumably because they're looked for in .NET Framework assemblies.

$jsonAssembly = &#39;C:\Users\user\Documents\WindowsPowerShell\Modules\newtonsoft.json.0.2.201\libs\Newtonsoft.Json.dll&#39;
# Specify the path to BouncyCastle.Cryptography.dll here.
$bouncyCastleAssembly = &#39;C:\path\to\BouncyCastle.Cryptography.dll&#39;

# !! Inexplicably, this is needed too, possibly also for BouncyCastle.Cryptography.dll
Add-Type -LiteralPath $jsonAssembly

Add-Type -ReferencedAssemblies $jsonAssembly, $bouncyCastleAssembly, System.Numerics -TypeDefinition @&#39;
using System;
using System.Numerics;
using Newtonsoft.Json;

public class BigIntegerConverter: JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Org.BouncyCastle.Math.BigInteger));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        BigInteger big = (BigInteger)reader.Value;
        return new Org.BouncyCastle.Math.BigInteger(big.ToString());
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value.ToString());
    }
&#39;@

Also note:

  • The addition of using System; to enable namespace-free references to class Type

  • The addition of System.Numerics to -ReferencedAssemblies as well as using System.Numerics; to allow namespace-free references to BigInteger

  • Adding public to the BigInterConverter class definition to ensure that the resulting class is public.

huangapple
  • 本文由 发表于 2023年6月22日 07:14:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76527697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定