c# - 函数中的参数类型验证 - 二进制模块与脚本模块

标签 c# powershell type-conversion

在构建了许多 PowerShell 模块(二进制和脚本)之后,这两个模型之间仍然存在我无法完全理解的不一致之处。也许你们中的一个人可以阐明这个问题。

  1. 想象一个接受单个 DateTime 值的函数。在脚本函数中,我会将其定义为 [DateTime] 参数;在 C# 函数中,参数的类型为 DateTime。到目前为止,一切顺利。

  2. 现在想象将一个 DateTime 传递给该函数,并使用 Add-Member 添加了一个额外的注释属性。尽管被定义为 [DateTime],脚本函数参数还是很乐意接受这个值,因为它实际上是一个 PSObject 包装了原始的 DateTime(并且可能包含其他成员)在使用时展开 - 我希望我在这里使用的是正确的术语。正如预期的那样,传递除(包装的)DateTime 之外的其他内容会失败,从而使该函数或多或少是类型安全的。

  3. 等效的 C# 函数将参数定义为 DateTime,因此据我所知,它无法访问附加参数。毕竟,参数提供的唯一“接口(interface)”来自 DateTime 类型。

  4. 或者,我可以将 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/

相关文章:

c++ - 跨 C 和 C++ 标准的可靠类型双关

c# - Math.Floor 或 Math.Truncate 与 (int) 在正数性能方面

c# - LINQ 加入以查找不在列表中的项目

C# 将日期从 xml(格式可能因地区而异)转换为 DateTime 数据类型

powershell - 如何在运行时通过脚本检查 PowerShell 中是否存在 cmdlet

windows - cmd 或 powershell 获取所有子目录

powershell 更新帮助失败

c# - html.dropdownlist 的 onchange 事件

c# - HttpContext.Current.Request.Form 复选框

c - 无法理解在 inet_ntoa 函数中完成的类型转换