二进制模块与脚本模块

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

  • 设想一个接受单个DateTime值的函数。 在脚本函数中,我将它定义为[DateTime]参数; 在C#函数中,参数的类型是DateTime 。 到现在为止还挺好。

  • 现在设想将一个DateTime传递给该函数,使用Add-Member将附加音符属性添加到该函数中。 尽管被定义为[DateTime] ,脚本函数参数会很乐意接受这个值,因为它实际上是一个包装原始DateTime (并且可能包含额外成员)的PSObject ,它在使用时被解包 - 我希望我使用的是正确的术语这里。 正如所料,传递(包装的) DateTime之外的东西将会失败,从而使该函数或多或少地具有类型安全性。

  • 等效的C#函数将参数定义为DateTime ,因此AFAIK无法访问附加参数。 毕竟,参数提供的唯一“接口”来自DateTime类型。

  • 或者,我可以将C#函数的参数类型定义为PSObject ,但是我必须对PSObjectBaseObject进行自己的类型检查。

  • 我的逻辑有缺陷吗? 或者更重要的是,有没有办法解决这个问题,这样我仍然可以将我的二进制模块的类型检查保留到PowerShell中?

    提前谢谢了!


    你们都是对的 - 它完全取决于目标参数是否是一个值类型(例如System.DateTime是一个结构体) - 在这种情况下,在参数绑定过程中,类型强制会丢失一切。

    但是,如果参数类型是参考类型,则可以使用PSObject.AsPSObject() “复活”PSObject包装器。

    我在纯(PowerShell)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!"
    

    他们现在都返回字符串值Hi there! 当您取消引用TestProperty成员时。

    现在进行实际测试:

    $TestObjectAfter = Test-PSObjectByRef -TestObject $TestObject
    $DateTimeAfter   = Test-PSObjectByValue -DateTime $DateTime
    

    这仍然会返回Hi there!

    $TestObjectAfter.TestProperty
    

    但是这不会:

    $DateTimeAfter.TestProperty
    
    链接地址: http://www.djcxy.com/p/41217.html

    上一篇: binary modules vs. script modules

    下一篇: Extending base class property in Typescript