将 Powershell PSCustomObject 复制到数组元素将传递引用,而不是值
Copying Powershell PSCustomObject to array element will pass reference, not value
不确定我做错了什么,但是在将 Powershell 中的 PSCustomObject 复制到数组元素时,这是通过引用复制的。
看到这个:
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = [PSCustomObject]@()
}
$mediaItem = [PSCustomObject]@{
description = "";
simpleMediaItem = [PSCustomObject]@{
fileName = "";
uploadToken = "";
}
}
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem.PsObject.Copy()
$mediaItem.description = "Friend of Rocker Duck"
$mediaItem.simpleMediaItem.fileName = "Donald Duck.txt"
$mediaItem.simpleMediaItem.uploadToken = "2222"
$body.newMediaItems += $mediaItem.PsObject.Copy()
$body | ConvertTo-Json -depth 4
输出:
{
"albumId": null,
"newMediaItems": [
{
"description": "Friend of Mickey Mouse",
"simpleMediaItem": {
"fileName": "Donald Duck.txt",
"uploadToken": "2222"
}
},
{
"description": "Friend of Rocker Duck",
"simpleMediaItem": {
"fileName": "Donald Duck.txt",
"uploadToken": "2222"
}
}
]
}
.psobject.Copy()
对 [pscustomobject]
个实例执行 浅(成员方面)克隆。
由于您的 simpleMediaItem
属性 包含对 .NET 引用类型 的引用(恰好是另一个 [pscustomobject]
实例),复制的是 reference,因此原始 [pscustomobject]
和通过 .psobject.Copy()
获得的克隆都引用 完全相同的对象.
对于深度(递归)克隆(没有通用解决方案),您必须创建自定义实现。
您可以使用自定义 class
定义完全避免该问题:
class MediaItem {
[string] $description
[pscustomobject] $simpleMediaItem = [pscustomobject] @{
fileName = ""
uploadToken = ""
}
}
现在,每次需要一个新的独立实例时,您只需使用 [MediaItem]::new()
。
总而言之:
class MediaItem {
[string] $description
[pscustomobject] $simpleMediaItem = [pscustomobject] @{
fileName = ""
uploadToken = ""
}
}
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = @()
}
# Create a new instance.
$mediaItem = [MediaItem]::new()
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem
# Create a new instance.
$mediaItem = [MediaItem]::new()
$mediaItem.description = "Friend of Rocker Duck"
$mediaItem.simpleMediaItem.fileName = "Donald Duck.txt"
$mediaItem.simpleMediaItem.uploadToken = "2222"
$body.newMediaItems += $mediaItem
$body | ConvertTo-Json -Depth 4
您所看到的是预料之中的,您只是在复制基础对象。我还建议您使用 function 或 class 来执行此操作,这样会容易得多,而且不需要复制。
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = [PSCustomObject]@()
}
$mediaItem = [PSCustomObject]@{
description = "";
simpleMediaItem = [PSCustomObject]@{
fileName = "";
uploadToken = "";
}
}
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem
$base = $mediaItem.PsObject.Copy()
$child = $mediaItem.simpleMediaItem.PSObject.Copy()
$base.description = "Friend of Rocker Duck"
$child.fileName = "Donald Duck.txt"
$child.uploadToken = "2222"
$base.simpleMediaItem = $child
$body.newMediaItems += $base
不确定我做错了什么,但是在将 Powershell 中的 PSCustomObject 复制到数组元素时,这是通过引用复制的。 看到这个:
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = [PSCustomObject]@()
}
$mediaItem = [PSCustomObject]@{
description = "";
simpleMediaItem = [PSCustomObject]@{
fileName = "";
uploadToken = "";
}
}
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem.PsObject.Copy()
$mediaItem.description = "Friend of Rocker Duck"
$mediaItem.simpleMediaItem.fileName = "Donald Duck.txt"
$mediaItem.simpleMediaItem.uploadToken = "2222"
$body.newMediaItems += $mediaItem.PsObject.Copy()
$body | ConvertTo-Json -depth 4
输出:
{
"albumId": null,
"newMediaItems": [
{
"description": "Friend of Mickey Mouse",
"simpleMediaItem": {
"fileName": "Donald Duck.txt",
"uploadToken": "2222"
}
},
{
"description": "Friend of Rocker Duck",
"simpleMediaItem": {
"fileName": "Donald Duck.txt",
"uploadToken": "2222"
}
}
]
}
.psobject.Copy()
对 [pscustomobject]
个实例执行 浅(成员方面)克隆。
由于您的 simpleMediaItem
属性 包含对 .NET 引用类型 的引用(恰好是另一个 [pscustomobject]
实例),复制的是 reference,因此原始 [pscustomobject]
和通过 .psobject.Copy()
获得的克隆都引用 完全相同的对象.
对于深度(递归)克隆(没有通用解决方案),您必须创建自定义实现。
您可以使用自定义 class
定义完全避免该问题:
class MediaItem {
[string] $description
[pscustomobject] $simpleMediaItem = [pscustomobject] @{
fileName = ""
uploadToken = ""
}
}
现在,每次需要一个新的独立实例时,您只需使用 [MediaItem]::new()
。
总而言之:
class MediaItem {
[string] $description
[pscustomobject] $simpleMediaItem = [pscustomobject] @{
fileName = ""
uploadToken = ""
}
}
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = @()
}
# Create a new instance.
$mediaItem = [MediaItem]::new()
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem
# Create a new instance.
$mediaItem = [MediaItem]::new()
$mediaItem.description = "Friend of Rocker Duck"
$mediaItem.simpleMediaItem.fileName = "Donald Duck.txt"
$mediaItem.simpleMediaItem.uploadToken = "2222"
$body.newMediaItems += $mediaItem
$body | ConvertTo-Json -Depth 4
您所看到的是预料之中的,您只是在复制基础对象。我还建议您使用 function 或 class 来执行此操作,这样会容易得多,而且不需要复制。
$body = [PSCustomObject]@{
albumId = $album_id;
newMediaItems = [PSCustomObject]@()
}
$mediaItem = [PSCustomObject]@{
description = "";
simpleMediaItem = [PSCustomObject]@{
fileName = "";
uploadToken = "";
}
}
$mediaItem.description = "Friend of Mickey Mouse"
$mediaItem.simpleMediaItem.fileName = "Goofy.txt"
$mediaItem.simpleMediaItem.uploadToken = "1111"
$body.newMediaItems += $mediaItem
$base = $mediaItem.PsObject.Copy()
$child = $mediaItem.simpleMediaItem.PSObject.Copy()
$base.description = "Friend of Rocker Duck"
$child.fileName = "Donald Duck.txt"
$child.uploadToken = "2222"
$base.simpleMediaItem = $child
$body.newMediaItems += $base