Write-TypeView.ps1
function Write-TypeView { <# .Synopsis Writes extended type view information .Description PowerShell has a robust, extensible types system. With Write-TypeView, you can easily add extended type information to any type. This can include: The default set of properties to display (-DefaultDisplay) Sets of properties to display (-PropertySet) Serialization Depth (-SerializationDepth) Virtual methods or properties to add onto the type (-ScriptMethod, -ScriptProperty and -NoteProperty) Method or property aliasing (-AliasProperty) .Link Out-TypeView .Link Add-TypeView #> [OutputType([string])] param( # The name of the type #|Default MyCustomTypeName #|MaxLength 255 [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [String] $TypeName, # A collection of virtual method names and the script blocks that will be used to run the virtual method. [ValidateScript({ if ($_.Keys | ? {$_-isnot [string]}) { throw "Must provide the names of script methods" } if ($_.Values | ? {$_ -isnot [ScriptBlock]}) { throw "Must provide script blocks to handle each method" } return $true })] [Hashtable]$ScriptMethod, # A Collection of virtual property names and the script blocks that will be used to get the property values. [ValidateScript({ if ($_.Keys | ? {$_ -isnot [string]}) { throw "Must provide the names of script properties" } if ($_.Values | ? {$_-isnot [ScriptBlock]} ) { throw "Must provide script blocks to handle each property" } return $true })] [Hashtable]$ScriptProperty, # A collection of fixed property values. [ValidateScript({ if ($_.Keys | ? { $_-isnot [string] } ) { throw "Must provide the names of note properties" } return $true })] [Hashtable]$NoteProperty, # A collection of property aliases [ValidateScript({ if ($_.Keys | ? { $_-isnot [string]}) { throw "Must provide the names of alias properties" } if ($_.Keys | ? {$_-isnot [string]}) { throw "Must provide the names of properties to alias" } return $true })] [Hashtable]$AliasProperty, # A collection of code methods. A code method maps a [ValidateScript({ if ($_.Keys | ? {$_-isnot [string]}) { throw "Must provide the names of code methods" } if ($_.Values | ? {$_-isnot [Reflection.MethodInfo]}) { throw "Must provide the static method to run" } return $true })] [Hashtable]$CodeMethod, # Any code properties for an object [ValidateScript({ if ($_.Keys |? {$_-isnot [string]}) { throw "Must provide the names of code properties" } if ($_.Values | ? {$_-isnot [Reflection.MethodInfo]}) { throw "Must provide the static method to run" } return $true })] [Hashtable]$CodeProperty, # The default display. If only one propertry is used, # this will set the default display property. If more than one property is used, # this will set the default display member set [string[]]$DefaultDisplay, # The ID property [string]$IdProperty, # The serialization depth. If the type is deserialized, this is the depth of subpropeties # that will be stored. For instance, a serialization depth of 3 would storage an object, it's # subproperties, and those objects' subproperties. You can use the serialization depth # to minimize the overhead of moving objects back and forth across the remoting boundary, # or to ensure that you capture the correct information. [int]$SerializationDepth = 2, # The reserializer type used for recreating a deserialized type [Type]$Reserializer, # Property sets define default views for an object. A property set can be used with Select-Object # to display just that set of properties. [ValidateScript({ if ($_.Keys | ? {$_ -isnot [string] } ) { throw "Must provide the names of property sets" } if ($_.Values | Where-Object {$_ -isnot [string] -and $_ -isnot [Object[]] }){ throw "Must provide a name or list of names for each property set" } return $true })] [Hashtable]$PropertySet, # Will hide any properties in the list from a display [string[]]$HideProperty ) process { $memberSetXml = "" #region Construct Member Set if ($psBoundParameters.ContainsKey('SerializationDepth') -or $psBoundParameters.ContainsKey('IdProperty') -or $psBoundParameters.ContainsKey('DefaultDisplay')) { $defaultDisplayXml = if ($psBoundParameters.ContainsKey('DefaultDisplay')) { $referencedProperties = "<Name>" + ($defaultDisplay -join "</Name> <Name>") + "</Name>" " <PropertySet> <Name>DefaultDisplayPropertySet</Name> <ReferencedProperties> $referencedProperties </ReferencedProperties> </PropertySet> " } $serializationDepthXml = if ($psBoundParameters.ContainsKey('SerializationDepth')) { " <NoteProperty> <Name>SerializationDepth</Name> <Value>$SerializationDepth</Value> </NoteProperty>" } else {$null } $ReserializerXml = if ($psBoundParameters.ContainsKey('Reserializer')) { " <NoteProperty> <Name>TargetTypeForDeserialization</Name> <Value>$Reserializer</Value> </NoteProperty> " } else { $null } $memberSetXml = " <MemberSet> <Name>PSStandardMembers</Name> <Members> $defaultDisplayXml $serializationDepthXml $reserializerXml </Members> </MemberSet> " } #endregion Construct Member Set #region PropertySetXml $propertySetXml = if ($psBoundParameters.PropertySet) { foreach ($NameAndValue in $PropertySet.GetEnumerator()) { $referencedProperties = "<Name>" + ($NameAndValue.Value -join "</Name> <Name>") + "</Name>" "<PropertySet> <Name>$([Security.SecurityElement]::Escape($NameAndValue.Key))</Name> <ReferencedProperties> $referencedProperties </ReferencedProperties> </PropertySet>" } } else { "" } #endregion #region Aliases $aliasPropertyXml = if ($psBoundParameters.AliasProperty) { foreach ($NameAndValue in $AliasProperty.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $NameAndValue.Key) { 'IsHidden="true"' } else { ""} " <AliasProperty $isHiddenChunk> <Name>$([Security.SecurityElement]::Escape($NameAndValue.Key))</Name> <ReferencedMemberName>$([Security.SecurityElement]::Escape($NameAndValue.Value))</ReferencedMemberName> </AliasProperty>" } } else { "" } #endregion Aliases $codeMethodXml = if ($psBoundParameters.CodeMethod) { foreach ($NameAndValue in $CodeMethod.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $NameAndValue.Key) { 'IsHidden="true"' } else { ""} " <CodeMethod $isHiddenChunk> <Name>$([Security.SecurityElement]::Escape($NameAndValue.Key))</Name> <CodeReference> <TypeName>$($NameAndValue.Value.DeclaringType)</TypeName> <MethodName>$($NameAndValue.Value.Name)</MethodName> </CodeReference> </CodeMethod>" } } else { "" } $codePropertyXml = if ($psBoundParameters.CodeProperty) { foreach ($NameAndValue in $CodeProperty.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $NameAndValue.Key) { 'IsHidden="true"' } else { ""} " <CodeProperty $IsHiddenChunk> <Name>$([Security.SecurityElement]::Escape($NameAndValue.Key))</Name> <CodeReference> <TypeName>$($NameAndValue.Value.DeclaringType)</TypeName> <MethodName>$($NameAndValue.Value.Name)</MethodName> </CodeReference> </CodeProperty>" } } else { "" } $NotePropertyXml = if ($psBoundParameters.NoteProperty) { foreach ($NameAndValue in $NoteProperty.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $NameAndValue.Key) { 'IsHidden="true"' } else { ""} " <NoteProperty $isHiddenChunk> <Name>$([Security.SecurityElement]::Escape($NameAndValue.Key))</Name> <Value>$([Security.SecurityElement]::Escape($NameAndValue.Value))</Value> </NoteProperty>" } } else { "" } $scriptMethodXml = if ($psBoundParameters.ScriptMethod) { foreach ($methodNameAndCode in $ScriptMethod.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $methodNameAndCode.Key) { 'IsHidden="true"' } else { ""} " <ScriptMethod $isHiddenChunk> <Name>$($methodNameAndCode.Key)</Name> <Script> $([Security.SecurityElement]::Escape($methodNameAndCode.Value)) </Script> </ScriptMethod>" } } else { "" } #region Script Property $scriptPropertyXml = if ($psBoundParameters.ScriptProperty) { foreach ($propertyNameAndCode in $ScriptProperty.GetEnumerator()) { $isHiddenChunk = if ($HideProperty -contains $propertyNameAndCode.Key) { 'IsHidden="true"' } else { ""} " <ScriptProperty $isHiddenChunk> <Name>$($propertyNameAndCode.Key)</Name> <GetScriptBlock> $([Security.SecurityElement]::Escape($propertyNameAndCode.Value)) </GetScriptBlock> </ScriptProperty>" } } $innerXml = @($memberSetXml) + $propertySetXml + $aliasPropertyXml + $codePropertyXml + $codeMethodXml + $scriptMethodXml + $scriptPropertyXml + $NotePropertyXml $innerXml = ($innerXml | ? {$_} ) -join ([Environment]::NewLine) " <Type> <Name>$TypeName</Name> <Members> $innerXml </Members> </Type>" } } |