Reputation: 360
I have C# class in an external DLL which I cannot modify. Two of the classes in the library are defined as follows which I need to use in my Powershell script.
public class MyCsharpClass<TKey, TValue> : ISomeBaseClass<TKey, TValue>
{
public MyCsharpClass(string path, ISomeBaseTranslator<TKey, TValue> translator)
{
...
}
}
...
...
public class MyByteTranslatorCSharpClass: ISomeBaseTranslator<byte[], byte[]>
{
...
}
I want to create instance of MyCsharpClass in Powershell script as follows:
$MyType = [MyCsharpClass[byte[],byte[]]]::new($Path, [MyByteTranslatorCSharpClass]::new())
But the above line fails with below error. I can just enter type name in PS ISE command window and get the same error.
PS C:\> [MyCsharpClass[byte[],byte[]]]
At line:1 char:30
+ [MyCsharpClass[byte[],byte[]]]
+ ~
Unexpected token ']' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Below line works fine though showing me the type info of my class when I just use byte type for TKey:
PS C:\> [MyCsharpClass[byte,byte[]]]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False MyCsharpClass System.Object
It seems the first closing bracket ']' for my Key type of byte[] confuses Powershell that type definition is being closed and so it raises error when it observes Unexpected token ']' in the end of expression.
I also tried to replace byte[] type with System.Collections.Generic.List type which works fine now for declaring a type.
PS C:\> MyCsharpClass[System.Collections.Generic.List[System.Byte],System.Collections.Generic.List[System.Byte]]]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False MyCsharpClass System.Object
However the constructor invocation fails this time while passing instance of MyByteTranslatorCSharpClass as second argument in constructor (at the end of below line).
$MyType = [MyCsharpClass[System.Collections.Generic.List[System.Byte],System.Collections.Generic.List[System.Byte]]]::new($Path, [MyByteTranslatorCSharpClass]::new())
This gives exception of 'System.Management.Automation.MethodException: Cannot convert argument "translator", with value: "MyByteTranslatorCSharpClass", for ".ctor" to type "ISomeBaseTranslator[System.Collections.Generic.List1[System.Byte],System.Collections.Generic.List
1[System.Byte]]"
Please let me know in this context, how can I create instance of MyCsharpClass with byte[] type for TKey and TValue generic arguments in Powershell. Please note that I can neither change the DLL side nor do I have its source.
Upvotes: 2
Views: 382
Reputation: 174505
This appears to be a type name parsing bug.
Fortunately, you can easily work around this by "qualifying" the type parameter literals with an extra pair of square brackets ([]
) :
[MyCsharpClass[[byte[]],[byte[]]]]::new(...)
... or by constructing the concrete type directly using reflection:
$myType = [MyCsharpClass`2].MakeGenericType(@([byte[]],[byte[]]))
$myType::new(...)
Upvotes: 3