2014-01-27 3 views
4

Когда явным образом бросаю свой новый объект (см. Первую строку кода), мой вновь созданный EntityReference сохраняется, не будучи обернутым в PSObject, и поэтому его сериализация работает просто отлично:Без явного приведения объект обертывается в PSObject

$entityRef1 = [Microsoft.Xrm.Sdk.EntityReference](new-object Microsoft.Xrm.Sdk.EntityReference("businessunit", [System.Guid]::NewGuid())) 
$unit = new-object Microsoft.Xrm.Sdk.Entity("businessunit") 
$unit.Attributes["parentbusinessunitid"] = $entityRef1 
$unit.Attributes["parentbusinessunitid"].GetType() # Produces "EntityReference" 

# Serialize $unit including the entityRef, and write its xml representation 
$serializer = New-Object System.Runtime.Serialization.DataContractSerializer($unit.GetType()) 
$stream = New-Object System.IO.MemoryStream 
$serializer.WriteObject($stream, $unit) 
$stream.Flush() 
$stream.Seek(0, [System.IO.SeekOrigin]::Begin) 
$reader = New-Object System.IO.StreamReader($stream) 
$reader.ReadToEnd() 

Однако, когда я не использую бросок:

$entityRef1 = (new-object Microsoft.Xrm.Sdk.EntityReference("businessunit", [System.Guid]::NewGuid())) 

Powershell жалуется, когда я хочу, чтобы сериализовать:
Exception calling "WriteObject" with "2" argument(s): "Type 'System.Management.Automation.PSObject' with data contract name 'PSObject:http://schemas.datacontract.org/2004/07/System.Management.Automation' is not expected.

Теперь я прочитал Why does Get-Date seem to return DateTime objects, but the BinarySerializer indicate it returns a PSObject?, и, казалось бы, что это та же самая проблема ....
за исключением того, что я использую Powershell 3,0 ($PSVersionTable.psversion производит версию 3.0.-1.-1) и что «неправильный» фрагмент кода из этого сообщения отлично работает в моей среде Powershell ...

В этом сообщении предлагается, чтобы новый движок, основанный на DLR от Powershell 3, больше не должен вызывать эти проблемы, поэтому были ли они слишком оптимистичны относительно что, или я столкнулся с чем-то еще?


Edit: Приведенный ниже код производит такое же поведение, не будучи зависимыми от SDK CRM. С броском, PowerShell жалуется не в состоянии сериализовать System.UriBuilder, в то время как без броска, он жалуется на получение System.Management.Automation.PSObject экземпляра:

# $uriBuilder = [UriBuilder](New-Object UriBuilder) 
$uriBuilder = (New-Object UriBuilder) 

$dict = new-object Hashtable 
$dict["mykey"] = $uriBuilder 
$dict["mykey"].GetType() # Produces "UriBuilder" 

# Serialize $dict including the uriBuilder, and write its xml representation 
$serializer = New-Object System.Runtime.Serialization.DataContractSerializer($dict.GetType()) 
$stream = New-Object System.IO.MemoryStream 
$serializer.WriteObject($stream, $dict) 
$stream.Flush() 
$stream.Seek(0, [System.IO.SeekOrigin]::Begin) 
$reader = New-Object System.IO.StreamReader($stream) 
$reader.ReadToEnd() 
+1

Возможно, вы столкнулись с ошибкой - v3 принесли несколько psobject для разворота ошибок для езды в течение периода альфы и беты. Возможно, их больше. Можете ли вы дать репрограмму, которая не требует XRM SDK?:) – x0n

+0

@ x0n: Совершено, я думаю, это демонстрирует то же поведение. – Astrotrain

+0

Ваш пример не работает в Powershell 2 ISE, потому что он не может найти DataContractSerializer, и я получаю 'New-Object: Не могу найти тип [System.Runtime.Serialization.DataContractSerializer]: убедитесь, что сборка, содержащая этот тип, загружена. В строке: 9 символов: 25 + $ serializer = Новый объект <<<< System.Runtime.Serialization.DataContractSerializer ($ dict.GetType()) + CategoryInfo: InvalidType: (:) [New-Object], PSArgumentException + FullyQualifiedErrorId: TypeNotFound, Microsoft.PowerShell.Commands.NewObjectCommand' – Ytrog

ответ

3

Да, это еще одна PSObject разворачивания ошибка, хотя после того, как я думал, я понял, что это известно командой powershell и, вероятно, останется «не исправит» какое-то время. Прежде чем проклинать их, подумайте об этом: когда psobjects (все неявно введенные) передаются методам .NET, они разворачиваются связующим, но не переписываются в перечисляемые объекты или не проверяют свойства, чтобы увидеть, нужно ли их разворачивать или нет , Честно говоря, на данный момент он не может знать, должно ли быть развернуто или нет, свойство, набранное как объект (например), содержащее psobject, так что оно ничего не делает. При необходимости распаковываются только экземпляры первого уровня.

Я думаю, что реальная ошибка здесь - и один стоит на входе connect.microsoft.com/powershell - это то, что экземпляр uribuilder не разворачивали, когда он назначен Хеш ключа. Мне кажется, что это будет недвусмысленная ситуация .

Золотое правило: PowerShell никогда не развяжет psobject, если целью назначения является объект.

Таким образом, временное решение заливка при создании или в пункте назначения:

$ht["foo"] = [uribuilder]$builder 

Командлет New-Object является причиной обертке. Когда командлет передает экземпляр в PSCmdlet.WriteObject, применяется обертка.

Надеюсь, это поможет.

+1

Спасибо за ваше объяснение , особенно о том, чтобы не разворачивать при назначении объекту, это действительно драгоценный камень. Эти разворачивающиеся ошибки не так уж плохи, чтобы компенсировать их, если вы знаете о них. Если вы не знаете, что это может происходить каждый раз в то время, это может заставить вас поцарапать вашу голову ... – Astrotrain

Смежные вопросы