[英]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.StackTrace
, System.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
编辑
详细说明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.