簡體   English   中英

在 PowerShell 中提供 C# 抽象 class 的實現

[英]Provide an implementation of a C# abstract class in PowerShell

我正在嘗試創建抽象 class ' function 的 PowerShell 類實現:

class ReadList : Intacct.SDK.Functions.AbstractFunction {

    [string]$ObjectName
    
    ReadList ([string]$ObjectName) {
        $this.ObjectName = $ObjectName
    }

    [void] WriteXml ( [Intacct.SDK.Xml.IaXmlWriter]$xml ) {

        $xml.WriteStartDocument()
        
        $xml.WriteStartElement("get_list")
        $xml.WriteAttributeString("object",$this.ObjectName)    
        $xml.WriteEndElement() # </get_list> 
    
        $xml.WriteEndDocument()
        $xml.Flush()
        $xml.Close()

    }

}

當我嘗試使用它時,我得到一個運行時異常:

創建類型“ReadList”時出錯。 錯誤消息:來自程序集 'PowerShell Class 程序集,版本 = 1.0.0.1 的“ReadList”類型中的方法“WriteXml”,| Culture=neutral, PublicKeyToken=null' 沒有實現。

我試過添加ref標簽:

[void] WriteXml ( [Intacct.SDK.Xml.IaXmlWriter][ref]$xml ) {

但我得到一個不同的錯誤:

方法參數上不允許有多個類型約束。

我做錯了什么,還是我試圖做的事情不受支持?

據我所知,這是不支持的。 我還沒有找到一個好的解決方法,或者一個簡潔地解釋它的資源。

從技術上講,第二個實現是正確的,但根據錯誤 PowerShell 不支持方法參數[1]上的多種類型約束。
通常這不是世界末日。 問題是當從抽象 class 繼承時,class 必須定義所有抽象方法[2] ,因此必須定義帶有簽名WriteXml (ref IaXmlWriter <ParameterName>)的方法。 其他任何東西都給出了Method 'WriteXml'... does not have an implementation.

即使 PowerShell 支持多種類型約束,我認為這不會按預期工作,因為c#與 PowerShell 的[ref]不同 - 創建[ref]是為了支持 ZD47C174ED277BDF06CFC72763AB7970Z 明確聲明它可以是文檔用於對 class 成員進行類型轉換[3]

我知道的唯一可行的解決方法是在c#中編寫ReadList class 定義,並通過Add-Type [4]添加到 PowerShell ......不是很好。

這一切都超出了我所知的scope; 也許有一個很好的解決方案,並且有更多專業知識的人可以糾正我。


參考
[1] 涉及此內容的 SO 帖子和 [ref] (下同)

查看$Error.Exception.StackTraceSystem.Management.Automation.ScriptBlock.Create正在引發異常。 Couldn't go further with PowerShell 5.1 but PowerShell Core files include a check for class method parameters here which points to the MultipleTypeConstraintsOnMethodParam exception that gets raised.

Scripting.Classes.BasicParsing.Tests.ps1檢查多種類型會引發MultipleTypeConstraintsOnMethodParam異常。

[2]抽象 class 的派生類必須實現所有抽象方法。
抽象類和密封類以及 Class 成員

[3] 涉及此約束和多種類型約束的 SO 帖子(同上)

class 成員不支持 PSReference 類型
about_Classes

[4] 將 .NET 類型添加到 session


編輯
詳細說明Add-Type解決方案

  • 使用ReferencedAssemblies傳入Intacct.SDK.dll和相關程序集。
  • 使用[Reflection.Assembly]加載這些程序集

指定版本時使用Load()或僅使用名稱的LoadFromPartialName() LoadFrom()指定路徑時使用 LoadFrom()。

$Assemblies = @(
    'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
    'System.Xml.ReaderWriter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
) |
foreach {
    [Reflection.Assembly]::Load($_)
}

$Assemblies += @(
    "$pwd/Microsoft.Extensions.Logging.Abstractions.dll"
    "$pwd/Intacct.SDK.dll"
) | foreach {
    [Reflection.Assembly]::LoadFrom($_)
}

Add-Type -TypeDefinition $Source -ReferencedAssemblies $Assemblies

我得出了同樣的結論,我需要創建一個 C# class 定義並導入它。

Push-Location ~/Desktop

$Source = @"
using Intacct.SDK.Functions;
using Intacct.SDK.Xml;

public class GetList : Intacct.SDK.Functions.AbstractFunction
{
    public string ObjectName;

    public GetList (string objectName) 
    {
        this.ObjectName = objectName;
    }

    public override void WriteXml( ref Intacct.SDK.Xml.IaXmlWriter xml )
    {
        xml.WriteStartDocument();        
        xml.WriteStartElement("get_list");
        xml.WriteEndDocument();
        xml.Flush();
    }
}
"@
    
# netstandard and ReaderWriter are located in `$PSHOME`; others on Desktop
$Assemblies = @(
    'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
    'System.Xml.ReaderWriter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    "$pwd/Microsoft.Extensions.Logging.Abstractions.dll"
    "$pwd/Intacct.SDK.dll"
)

# using ReferenceAssemblies based on a suggestion from the PowerShell Slack channel
$Type = Add-Type -TypeDefinition $Source -ReferencedAssemblies $Assemblies -PassThru

$GetList = [GetList]::new('something')
$GetList

這會產生錯誤:

Add-Type: getlist.ps1:37:9
Line |
  37 |  $Type = Add-Type -TypeDefinition $Source -ReferencedAssemblies $Assem …
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to load one or more of the requested types. Could not load file or assembly 'Intacct.SDK, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The parameter is incorrect.  (0x80070057 (E_INVALIDARG))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM