我正在尝试创建 abstract class 的 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()
}
}
当我尝试使用它时,出现运行时异常:
Error during creation of type "ReadList". Error message: Method 'WriteXml' in type 'ReadList' from assembly 'PowerShell Class Assembly, Version=1.0.0.1, | Culture=neutral, PublicKeyToken=null' does not have an implementation.
我尝试添加 ref
标签:
[void] WriteXml ( [Intacct.SDK.Xml.IaXmlWriter][ref]$xml ) {
但是我得到了一个不同的错误:
Multiple type constraints are not allowed on a method parameter.
我做错了什么,还是我试图做的事情不受支持?
最佳答案
据我所知,这是不支持的。我无法找到一个好的解决方法,或者一个可以简洁解释它的资源。
从技术上讲,第二种实现是正确的,但根据错误 PowerShell 不支持方法参数的多个类型约束[1]。
通常这并不是世界末日。问题是当从抽象类继承时,该类必须定义所有抽象方法 [2],因此具有签名 WriteXml (ref IaXmlWriter <ParameterName>)
的方法必须被定义。其他任何东西都会给出 Method 'WriteXml' ... does not have an implementation.
即使 PowerShell 支持多种类型约束,我也不认为这会按预期工作,因为 c#
与 PowerShell 的 [ref]
不一样-[ref]
创建它是为了支持 COM 对象,并且文档明确指出它不能用于对类成员进行类型转换[3]。
我知道在这里可能有效的唯一解决方法是编写 ReadList
c#
中的类定义,并通过 Add-Type
添加到 PowerShell [4]...不太好。
这一切都超出了我的知识范围;也许有一个好的解决方案,并且有更多专业知识的人可以纠正我。
引用文献
[1] SO post that touches on this and [ref] (下同)
查看$Error.Exception.StackTrace
, System.Management.Automation.ScriptBlock.Create
正在引发异常。无法进一步使用 PowerShell 5.1,但 PowerShell Core 文件包含对类方法参数的检查 here它指向 MultipleTypeConstraintsOnMethodParam
引发的异常。
Scripting.Classes.BasicParsing.Tests.ps1
检查多种类型将引发 MultipleTypeConstraintsOnMethodParam
异常。
[2] 抽象类的派生类必须实现所有抽象方法。
Abstract and Sealed Classes and Class Members
[3] SO post that touches on this and multiple type constraints (同上)
类成员不支持 PSReference 类型
about_Classes
[4] Add a .NET type to a session
编辑
详细说明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
关于c# - 在 PowerShell 中提供 C# 抽象类的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65888312/