Using non-standard parameter data types in Powershell advanced functions
I've noticed that most Powershell advanced functions declare parameters of standard datatypes (string, int, bool, xml, array, hashtable, etc.) which map to specific .Net types.
How would one declare an advanced function parameter using another .Net data type? For example, here is a contrived example:
function Do-Something
{
[CmdletBinding()]
Param(
[System.Xml.XPathNodeList] $nodeList
)
Begin {}
Process
{
Foreach ($node in $nodeList)
{
Write-Host $node
}
}
End {}
}
# Prepare to call the function:
$xml = [xml](get-content .\employee.xml)
$nodeList = $xml.SelectNodes("//age")
# Call the function passing an XPathNodeList:
do-something $nodeList
Invoking this function results in the following runtime error:
Unable to find type [System.Xml.XPathNodeList]: make sure that the assembly
containing this type is loaded.
Can this be accomplished with LoadWithPartialName()? How?
Assuming this is possible, here's an 开发者_Python百科ancillary question: would using non-standard types this way go against 'best practice'?
It is OK to use custom .NET types as long as you use something like the cmdlet Add-Type
to load the assembly that defines the custom type. However in this case, the assembly, System.Xml
, is already loaded. Your problem arises because the type you specified is a private type i.e. only visible within the System.Xml
assembly.
PS> $nodeList.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False False XPathNodeList System.Xml.XmlNodeList
Use its public base class instead:
[CmdletBinding()]
Param(
[Parameter()]
[System.Xml.XmlNodeList]
$nodeList
)
You shouldn't have any issues with using standard .NET objects as function parameters - the error you're getting is associated with unloaded assemblies, and that's where I'd look. Check your profile to make sure there's nothing unusual happening - see http://msdn.microsoft.com/en-us/library/bb613488%28v=vs.85%29.aspx for details.
If it really comes to it, you can use the following to load System.Xml (casting to Void to suppress the text output of loading):
[Void][System.Reflection.Assembly]::LoadWithPartialName("System.Xml")
精彩评论