Try to implement any interfaces that is intended to be implemented in terms of yourself, E.g. IEquatable, IComparable:
class ServerName : Object, System.IEquatable[ServerName] {
[string]$ComputerName
[bool] Equals([ServerName]$other) {
return $this.ComputerName.Equals($other.ComputerName);
}
}
I should be able to write IEquatable<T> and IComparable<T> classes
A runtime compile error:
An error occurred while creating the pipeline.
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : RuntimeException
Any version of PowerShell since classes were introduced, up to and including 7 Pre 4
It's obviously not the same, but just to mention an interim workaround: use [object] instead of your own type.
/cc @SeeminglyScience for reference #10623
Yeah this does repro without the specifics of #10623 (e.g. without the making the engine check overloads)
PS> Add-Type -IgnoreWarnings -TypeDefinition 'public interface ISomething<T> { }'
PS> class Test : ISomething[Test] { }
# At line:1 char:14
# + class Test : ISomething[Test] { }
# + ~~~~~~~~~~~~~~~~
# Unable to find type [ISomething[Test]].
# + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
# + FullyQualifiedErrorId : TypeNotFound
Presumably because it's attempting type resolution without taking the current type definition into account.
Also about valuetypes (assuming the title wasn't a mistake) #10231 is also relevant.
This works. But shouldn't. And just like @mklement0 wrote, it's not the same as what you want, but a workaround. (I got seriously distracted going down the rabbit hole that is stuff not implemented by classes.)
Class ServerName: System.Collections.IEqualityComparer
{
[String] $ComputerName
ServerName( [String] $serverName )
{
$this.ComputerName = $serverName
}
ServerName()
{
$this.ComputerName = ''
}
[Bool] Equals( $x, $y) { return $x -eq $y }
[Bool] Equals( $x ) { return $this.ComputerName -eq $x }
[Int] GetHashCode( $x ) { return $x.GetHashCode() }
}
$b = [ServerName]::new( 's1' )
$b -eq 's1'
$b -eq 's2'
$b.GetHashCode( $b )
I came across this issue trying to implement IObserver for CIM to do get-ciminstance asynchronously basically.
using namespace Microsoft.Management.Infrastructure
class CimObserver : Iobserver[CimInstance] {
[void] onNext(
[CimInstance]$cimInstance
) {$null}
}
At line:2 char:1
+ class CimObserver : Iobserver[CimInstance] {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error during creation of type "CimObserver". Error message:
Method 'OnNext' in type 'CimObserver' from assembly 'PowerShell Class Assembly, Version=1.0.0.8, Culture=neutral, PublicKeyToken=null' does not have an implementation.
Unless someone can tell me what I'm doing wrong.
@JustinGrote Method names are case sensitive for declaration:
using namespace Microsoft.Management.Infrastructure
class CimObserver : IObserver[CimInstance] {
[void] OnNext([CimInstance] $value) {}
[void] OnError([Exception] $exception) {}
[void] OnCompleted() {}
}
Though be aware that it's likely that OnNext will be called on a thread without a default runspace. If that's the case, the method will just throw.
@SeeminglyScience thanks. Believe it or not it totally worked :) Full code:
using namespace Microsoft.Management.Infrastructure
class CimObserver : System.IObserver[CimInstance] {
[void] OnNext(
[CimInstance]$ciminstance
) {
write-host -fore green $cimInstance
}
[void] OnError([Exception]$Exception) {throw $exception}
[void] OnCompleted() {$this.Unsubscribe()}
}
$query = (new-cimsession).QueryInstancesAsync('root/cimv2','WQL','SELECT * FROM Win32_ComputerSystem')
$observer = new-object CimObserver
$query.subscribe($observer)
Outputted the textual representation in green to the host.
Most helpful comment
@SeeminglyScience thanks. Believe it or not it totally worked :) Full code:
Outputted the textual representation in green to the host.