I am trying to use the method outlined here to create a number of custom data types, and rather than having a line for each I would like to define a hash table of the names and types like this
$pxAccelerators = @{
pxListObject = '[System.Collections.Generic.List[Object]]'
pxListString = '[System.Collections.Generic.List[String]]'
pxOrderedDictionary = '[System.Collections.Specialized.OrderedDictionary]'
}
Then I could use something like this
$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($key in $pxAccelerators.Keys) {
$name = $key
$type = $pxAccelerators.$key
$typeAccelerators::Add($key,$type)
}
to loop through the hash table and add each one.
However, the issue of course is that $type
isn't an actual type, it's a string. And $typeAccelerators::Add($key,$type)
needs a string and an actual type. So basically I need to coerce a string like '[System.Collections.Specialized.OrderedDictionary]'
to the actual type. I have found plenty of references to casting or coercing from one data type to another, but I can't seem to find any reference to how to convert a string to a type as defined BY the string.
I have tried all these stabs in the dark
([System.Type]'[System.Collections.ArrayList]')::new()
[System.Type]'[System.Collections.ArrayList]'
[System.Type]'[System.Collections.ArrayList]' -as [System.Type]
'[System.Collections.ArrayList]' -as ([PowerShell].Assembly.GetType('[System.Collections.ArrayList]')
to no avail.
$type = ([PowerShell].Assembly.GetType('[System.Collections.ArrayList]'))
seems to work, in that it doesn't throw an exception. But $type.GetType()
does throw You cannot call a method on a null-valued expression.
.
Interestingly, auto completion with [PowerShell].Assembly.GetType('[System.Collections.ArrayList]').
shows properties like BaseType
and FullName
are available, suggesting that I have actually produced a type, but using .GetType()
on the result throws an exception.
I tried
$pxAccelerators = @{
pxListObject = 'System.Collections.Generic.List[Object]'
pxListString = 'System.Collections.Generic.List[String]'
pxOrderedDictionary = 'System.Collections.Specialized.OrderedDictionary'
}
$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($key in $pxAccelerators.Keys) {
$name = $key
$type = [PowerShell].Assembly.GetType($pxAccelerators.$key)
$typeAccelerators::Add($key,$type)
}
[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get
and the accelerators are being added, but the type to be acclerated is not there, suggesting that the GetType()
line is not actually producing a type.
Lastly, I found this which seems to be getting closer. But I can't seem to rock how to access the method without starting from some sort of type already, and [System.Type].GetType('System.Int32')
is throwing, so that seems to be a dead end.
Am I trying to do something impossible? Or just missing the proper mechanism?
-as [type]
will doThe -as
operator gladly takes a type name as it's right-hand side operand.
Change the values of your dictionary to contain just a valid type name, and it becomes as easy as:
$pxAccelerators = @{
pxListObject = 'System.Collections.Generic.List[Object]'
pxListString = 'System.Collections.Generic.List[String]'
pxOrderedDictionary = 'System.Collections.Specialized.OrderedDictionary'
}
$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($acc in $pxAccelerators.GetEnumerator()) {
$name = $acc.Key
$type = $acc.Value -as [type]
$typeAccelerators::Add($name,$type)
}
Result:
PS ~> [pxOrderedDictionary] -is [type]
True
PS ~> [pxOrderedDictionary].FullName
System.Collections.Specialized.OrderedDictionary