【问题标题】:Defining Custom Powershell Objects定义自定义 Powershell 对象
【发布时间】:2016-10-08 01:59:41
【问题描述】:

在 Powershell 中有许多不同的方法来创建对象。我将其发布为纯粹在 Powerhell 中创建对象的挑战。我正在寻找一种使用满足这些要求的 Add-Type 创建对象的方法:

  1. 强类型对象属性
  2. 已实例化,使用:New-Object[My.Object]::New()[My.Object]@{'Property'='Value'}
  3. 自定义命名空间的一部分(即 [My.Object])
  4. 可以进行类型检查。示例:$myVar -is [My.Object]

我知道可以在 Visual Studio 中创建 dll 来实现这一点,但我正在寻找一种纯粹的 Powershell 方法来创建对象。

这是我拥有的满足上述规则的最接近的示例:

PS C:\> $memberDef = @"
public String myString { get; set; }
public int myInt { get; set; }
"@

PS C:\> Add-Type -Namespace "My.Namespace" -Name "Object" -MemberDefinition $memberDef

PS C:\> $myObj = [My.Namespace.Object]@{'myString'='Foo'; 'myInt'=42}
PS C:\> $myObj

myString myInt
-------- -----
Foo         42

话虽如此,是否有其他(可能更好)方法来创建外观、感觉和行为类似于原生 Powershell 对象的对象?

不满足所有规则的示例

弱类型对象属性:

PS C:\> $myObj = "" | Select-Object -Property myString, myInt

PS C:\> $myObj = New-Object -TypeName PSObject -Property @{'myString'='foo'; 'myInt'=42}


PS C:\> $myObj = @{}; $myObj.myString = 'foo'; $myObj.myInt = 42

PS C:\> $myObj.myInt = "This should result in an error."

没有命名空间的对象:

PS C:\> $typeDef = @"
public class myObject {
   public string myString { get; set; }
   public int myInt { get; set; }
}
"@
PS C:\> Add-Type -TypeDefinition $typeDef
PS C:\> $myObj = [myObject]::new()

PS C:\> $myObj = New-Object -TypeName PSObject -Property @{'myString'='foo'; 'myInt'=42}
PS C:\> $myObj.PSObject.TypeNames.Insert(0, "myObject")

【问题讨论】:

  • 我喜欢你的意思。我认为您所要求的在纯 PowerShell 中是不可能的。这是我所知道的最好的:powershellstation.com/2016/05/22/custom-objects-and-pstypename
  • 我在上面发布的示例几乎涵盖了所有规则。但我确信仍然需要做一些事情才能使它像一个原生的 Powershell 对象。啊,是的,您的 PSTypeName 链接很好,它添加了一个类型名称,因此您可以对它们使用 format.ps1xml 格式。我会将它添加到上面的示例中。

标签: c# powershell powershell-3.0 powershell-4.0 powershell-5.0


【解决方案1】:
  1. 强类型对象

您将获得的最接近的是显式类型变量。这可以通过在赋值期间强制转换变量来实现:

PS C:\> [My.Namespace.Object]$myObj = [My.Namespace.Object]@{'myString'='Foo'; 'myInt'=42}
PS C:\> $myObj = 123
Cannot convert the "123" value of type "System.Int32" to type "My.Namespace.Object".
At line:1 char:1
+ $myObj = 123
+ ~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

如您所见,这导致$myObj 只接受可以隐式转换为类型的新赋值。

【讨论】:

  • 当我写这个问题时,我正在寻找强类型对象属性。但你是对的,上面最好的例子确实阻止了无法转换为这种类型的对象被分配。我编辑了我的问题,使其更具体。感谢您的回复。
  • 这里的实际问题是什么? “强类型对象属性”究竟是什么意思?
  • 问题是如何更好地纯粹在 Powershell 中制作自定义对象,该对象的行为就像原生 powershell 对象一样。至于“强类型对象属性”,我正在寻找具有无法更改类型的属性的对象(请参阅上面的弱类型对象属性示例。)
  • 你不能,除非你像第一个例子那样编译一个类,或者(在 5.0+ 版本中)定义一个类并创建一个 ::new() 实例
【解决方案2】:

这是我发现在 Powershell 中创建一个对象的最佳方法,该对象是命名空间的一部分并涵盖上述所有规则。

PS C:\> $memberDef = @"
public String myString { get; set; }
public int myInt { get; set; }
"@

PS C:\> Add-Type -Namespace "My.Namespace" -Name "Object" -MemberDefinition $memberDef

PS C:\> $myObj = [My.Namespace.Object]@{'myString'='Foo'; 'myInt'=42}
PS C:\> $myObj

myString myInt
-------- -----
Foo         42

【讨论】:

    猜你喜欢
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多