开发者

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")
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜