I have a PowerShell class, which I want to automatically be convertable from string.
So I defined a TypeConverter like this:
class StringToAcmeStateConverter : System.Management.Automation.PSTypeConverter {
[bool] CanConvertFrom([object] $object, [Type] $destinationType) {
if($object -is [string]) {
return Test-Path ([string]$object);
}
return $false;
}
[bool] CanConvertTo([object] $object, [Type] $destinationType) {
return $false
}
[object] ConvertFrom([object] $sourceValue, [Type] $destinationType,
[IFormatProvider] $formatProvider, [bool] $ignoreCase)
{
if($null -eq $sourceValue) { return $null; }
if(-not $this.CanConvertFrom($sourceValue, $destinationType)) {
throw [System.InvalidCastException]::new();
}
$paths = [AcmeStatePaths]::new($sourceValue);
return [AcmeDiskPersistedState]::new($paths, $false, $true);
}
[object] ConvertTo([object] $sourceValue, [Type] $destinationType,
[IFormatProvider] $formatProvider, [bool] $ignoreCase)
{
throw [System.NotImplementedException]::new();
}
}
[System.ComponentModel.TypeConverter([StringToAcmeStateConverter])]
<# abstract #> class AcmeState {
AcmeState() {
if ($this.GetType() -eq [AcmeState]) {
throw [System.InvalidOperationException]::new("This is intended to be abstract - inherit To it.");
}
}
<# omitted #>
}
(Full code listing here: https://raw.githubusercontent.com/PKISharp/ACMESharpCore-PowerShell/deep-state/ACME-PS/internal/classes/AcmeState.ps1)
But PowerShell now throws a NullRefException from inside the pipeline. How would I make PS use the Converter correctly.
Update
Since this question did not contain enough information for a full repro, I created a gist containing the current (failing) code of the module: gist.github.com/glatzert/ba32f291b9155e6d19c29fbe9594a7c5
TypeConversion with PowerShell classes has some non-obvious issues.
My first approach with the TypeConverter-Attribute fails with either an NullRefException or UnknownTypeException (this depends on the order of the classes in your *.ps1).
I dug into the Types.ps1xml and created the following xml:
<Types>
<Type>
<Name>AcmeState</Name>
<TypeConverter>
<TypeName>StringToAcmeStateConverter</TypeName>
</TypeConverter>
</Type>
</Types>
and added TypesToProcess to the .psd1 pointing to the aforementioned ps1xml.
This will fail, stating the Converter is not known, which probably means, that PowerShell will process that file either in another context as the module or prior to loading the module.
To fix that problem, I removed the TypesToProcess from the .psd1 and added Update-TypeData Types.ps1xml as last line to my module, thus it will be run automatically during module import - and voila! This works.
TLDR:
If you want to register a TypeConverter defined in a PowerShell class, you need to use Update-TypeData
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With