2

我正在尝试创建一个抽象类' 函数的 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 类程序集,版本 = 1.0.0.1,|的“ReadList”类型中的方法“WriteXml” Culture=neutral, PublicKeyToken=null' 没有实现。

我试过添加ref标签:

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

但我得到一个不同的错误:

方法参数上不允许有多个类型约束。

我做错了什么,还是我试图做的事情不受支持?

4

2 回答 2

2

据我所知,这是不支持的。我还没有找到一个好的解决方法,或者一个简洁地解释它的资源。

从技术上讲,第二个实现是正确的,但根据错误 PowerShell 不支持方法参数[1]上的多个类型约束。
通常这不是世界末日。问题是从抽象类继承时,该类必须定义所有抽象方法[2]WriteXml (ref IaXmlWriter <ParameterName>) ,因此必须定义带有签名的方法。其他任何东西都会给出Method 'WriteXml' ... does not have an implementation.

即使 PowerShell 支持多种类型约束,我也不认为这会按预期工作,因为它c#与 PowerShell 不同[ref]-[ref]是为了支持 COM 对象而创建的,并且文档明确指出它不能用于类型转换类成员[3]

我知道的唯一可行的解​​决方法是在 中编写ReadList类定义,并通过[4]c#添加到 PowerShell ......不是很好。Add-Type

这一切都超出了我的知识范围;也许有一个很好的解决方案,并且有更多专业知识的人可以纠正我。


参考文献
[1] 涉及此内容的 SO 帖子和 [ref](下同)

看着$Error.Exception.StackTraceSystem.Management.Automation.ScriptBlock.Create正在引发异常。PowerShell 5.1 无法更进一步,但 PowerShell Core 文件在此处包含对类方法参数的检查,它指向MultipleTypeConstraintsOnMethodParam引发的异常。

Scripting.Classes.BasicParsing.Tests.ps1检查多种类型会引发MultipleTypeConstraintsOnMethodParam异常。

[2] 抽象类的派生类必须实现所有抽象方法。
抽象类和密封类以及类成员

[3] 涉及此约束和多种类型约束的 SO 帖子(同上)

类成员about_Classes不支持 PSReference 类型

[4] 将 .NET 类型添加到会话中


编辑
详细说明Add-Type解决方案

  • 用于ReferencedAssemblies传入Intacct.SDK.dll和依赖程序集。
  • 使用加载这些程序集[Reflection.Assembly]

Load()在指定版本或仅使用LoadFromPartialName()名称时使用,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
于 2021-01-26T03:08:14.090 回答
0

我得出了同样的结论,即我需要创建一个 C# 类定义并导入它。

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))
于 2021-01-26T04:01:34.563 回答