在构建了许多 PowerShell 模块(二进制和脚本)之后,这两个模型之间仍然存在我无法完全理解的不一致之处。也许你们中的一个人可以阐明这个问题。
想象一个接受单个
DateTime
值的函数。在脚本函数中,我会将其定义为[DateTime]
参数;在 C# 函数中,参数的类型为DateTime
。到目前为止,一切顺利。现在想象将一个
DateTime
传递给该函数,并使用Add-Member
添加了一个额外的注释属性。尽管被定义为[DateTime]
,脚本函数参数还是很乐意接受这个值,因为它实际上是一个PSObject
包装了原始的DateTime
(并且可能包含其他成员)在使用时展开 - 我希望我在这里使用的是正确的术语。正如预期的那样,传递除(包装的)DateTime
之外的其他内容会失败,从而使该函数或多或少是类型安全的。等效的 C# 函数将参数定义为
DateTime
,因此据我所知,它无法访问附加参数。毕竟,参数提供的唯一“接口(interface)”来自DateTime
类型。或者,我可以将 C# 函数的参数类型定义为
PSObject
,但是我必须自己对PSObject
的类型进行检查基础对象
。
我的逻辑有问题吗?或者,更重要的是,是否有解决此问题的方法,以便我仍然可以将二进制模块的类型检查留给 PowerShell?
非常感谢!
最佳答案
你既对又错 - 这完全取决于目标参数是否为值类型(例如 System.DateTime
是一个结构) - 在这种情况下,一切都在类型上丢失参数绑定(bind)期间的强制。
但是,如果参数类型是引用类型,您可以使用 PSObject.AsPSObject()
“恢复”PSObject 包装器| .
为了便于复制,我在纯(-ish)PowerShell 中提出了以下示例,但我相信它充分说明了我的观点
将以下内容粘贴到 C# 源文件中(例如,TestCmdlets.cs
):
using System;
using System.Management.Automation;
namespace TestPSObject
{
// This will be our parameter type
public class TestObject {}
// This will be our reference type test cmdlet
[Cmdlet(VerbsDiagnostic.Test, "PSObjectByRef")]
public class TestPSObjectByRefCommand : Cmdlet
{
[Parameter(Mandatory=true)]
public TestObject TestObject
{
get { return testObject; }
set { testObject = value; }
}
private TestObject testObject;
protected override void ProcessRecord()
{
// If this works, we should receive an object with
// identical psextended properties
WriteObject(PSObject.AsPSObject(this.TestObject));
}
}
// This will be our value type test cmdlet
[Cmdlet(VerbsDiagnostic.Test, "PSObjectByValue")]
public class TestPSObjectByValueCommand : Cmdlet
{
[Parameter(Mandatory=true)]
public DateTime DateTime
{
get { return dateTime; }
set { dateTime = value; }
}
private DateTime dateTime;
protected override void ProcessRecord()
{
// If this works, we should receive an object with
// identical psextended properties (hint: we won't)
WriteObject(PSObject.AsPSObject(this.DateTime));
}
}
}
现在,在您的 shell 中,编译并导入我们的测试模块:
Add-Type -Path .\TestCmdlets.cs -OutputAssembly TestPSObject.dll -OutputType Library
Import-Module .\TestPSObject.dll
接下来我们创建我们的测试对象并为它们添加一个注释属性:
$TestObject = New-Object TestPSObject.TestObject
$TestObject |Add-Member -MemberType NoteProperty -Name TestProperty -Value "Hi there!"
$DateTime = Get-Date
$DateTime |Add-Member -MemberType NoteProperty -Name TestProperty -Value "Hi there!"
当您取消引用 TestProperty
成员时,它们现在都返回字符串值 Hi there!
。
现在进行实际测试:
$TestObjectAfter = Test-PSObjectByRef -TestObject $TestObject
$DateTimeAfter = Test-PSObjectByValue -DateTime $DateTime
这仍然会返回你好!
:
$TestObjectAfter.TestProperty
但这不会:
$DateTimeAfter.TestProperty
关于c# - 函数中的参数类型验证 - 二进制模块与脚本模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48403276/