I'm trying to build a Method inside a Class, that accepts the required return type as a parameter. An example of this, is the System.Web.Script.Serialization.JavaScriptSerializer Class, Deserialize Method. It takes two parameters, A JSON text and the return type that it is expected to return. If I were to do something like below, and provided the $JSONConect contains valid information about the Class I want to use, I get a proper Object of type [Test]
$JSSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$JSONObject = [MyData]::New( )
If( $JSONContent -ne $null )
{
$JSONObject = $JSSerializer.Deserialize( $JSONContent, [MyData] )
}
I have tried building something this, but I get errors on the return type.
class Test
{
[Type] TestType( [Type]$AParam )
{
Write-Host "Your provided the type : $AParam"
$Result = New-Object $AParam
Write-Host "Your provided the value : $Result"
Switch( $AParam )
{
"bool"
{
Write-Host "Your provided the type : `"Boolean`""
$Result = $True
}
"int"
{
Write-Host "Your provided the type : `"Integer`""
$Result = 2
}
"string"
{
Write-Host "Your provided the type : `"String`""
$Result = "Miep"
}
Default
{
Write-Host "Your provided the type : `"Invalid!`""
$Result = $null
}
}
#$Result = [$AParam.GetType( )]
#return $Result
#return [Type]$( $AParam )
return Write-Output -NoEnumerate $Result
}
}
[bool]$tBool = $False
[int]$tInt = 0
[string]$tString = ""
$MyTest = [Test]::New( )
$tBool = $MyTest.TestType( [bool] )
$tBool
exit
$tInt = $MyTest.TestType( [int] )
$tInt
$tString = $MyTest.TestType( [string] )
$tString
#$MyTest.TestType( $tBool )
#$MyTest.TestType( $tInt )
#$MyTest.TestType( $tString )
The code above works partially, I can provide just a Type as parameter. But it will not return anything. As you can see, I have tried three ways to get this working, but I keep getting errors.
With the code as-is above, I get the following error:
Your provided the type : bool
Your provided the value : False
Your provided the type: "Boolean"
Cannot convert value "True" to type "System.Type". Error: "Invalid cast from 'System.Boolean' to 'System.Type'."
At D:\ParameterTypePassingUsng.ps1:39 char:16
+ return Write-Output -NoEnumerate $Result
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastIConvertible
False
Any suggestions on how to get this work, if it's at all possible? I cannot do this with CmdLets, because I just reworked my entire library to use classes instead of a collection of separate functions.
Hinted out by Mathias, what seemed you were looking for is known as Generic Methods in C# however PowerShell classes don't support this feature.
The error is telling you that in your method signature you're stating that the method will take a Type
as input and return a Type
as output and you aren't fulfilling this contract since you're returning the instance of a type or $null
(int
, string
, bool
or $null
).
By changing the signature to return type of [object]
the code would work properly:
[object] TestType([Type] $AParam)
You also will need to remove Write-Output -NoEnumerate
, just return $result
otherwise in PowerShell 7+ you will get unexpected return type of List<object>
, for example:
(Write-Output 1 -NoEnumerate).GetType() # List<object>
It's also unclear what you want to do with $Result = New-Object $AParam
, should be removed.
In summary the definition should be:
class Test {
[Object] TestType([Type] $AParam) {
Write-Host "You provided the type : $AParam"
$Result = $null
switch ($AParam) {
([bool]) {
Write-Host "You provided the type : `"Boolean`""
$Result = $True
}
([int]) {
Write-Host "You provided the type : `"Integer`""
$Result = 2
}
([string]) {
Write-Host "You provided the type : `"String`""
$Result = 'Miep'
}
Default {
Write-Host "You provided the type : `"Invalid!`""
}
}
return $Result
}
}
Using Generics in C# the code could be something like:
public static class Test
{
public static T? TestType<T>()
{
Type type = typeof(T);
object? result = type switch
{
_ when type == typeof(bool) => true,
_ when type == typeof(int) => 2,
_ when type == typeof(string) => "Miep",
_ => null
};
Console.WriteLine(
$"You provided the type : '{result?.GetType().Name ?? "Invalid!"}'");
return (T?)result;
}
}