Skip to content

Instantly share code, notes, and snippets.

@idavis
Created October 11, 2012 20:35
Show Gist options
  • Select an option

  • Save idavis/3875305 to your computer and use it in GitHub Desktop.

Select an option

Save idavis/3875305 to your computer and use it in GitHub Desktop.
Mimicking ruby's open classes with PowerShell
# new and def are used for lack of good PowerShell compatible API names. I want simple and easy to understand for this example.
function def {
param([string]$name, [scriptblock] $initializer)
# Create the static instance registry to mimic the CTS's single class instance per type
if($Global:__CTS__ -eq $null) {
$dictionary = (New-Object -TypeName 'System.Collections.Generic.Dictionary[string,object]' -ArgumentList @([StringComparer]::OrdinalIgnoreCase))
$value = [PSObject]::AsPSObject($dictionary)
$Global:__CTS__ = $value
}
$registry = $Global:__CTS__
$blocks = $registry[$name]
$blocks = @($blocks + $initializer)
$registry[$name] = $blocks
}
function new {
param([string]$name)
$registry = $Global:__CTS__
$blocks = $registry[$name]
if(!$blocks) { throw "No known type $name" }
$module = New-Module {}
$blocks | % { . $module $_ } # dot source each block into the module's scope
$prototype = $module.AsCustomObject()
$prototype.PSTypeNames.Insert(0,"$name")
if($prototype.Initialize) {
$prototype.Initialize.Invoke( $args[0..($args.Length-1)] )
}
$prototype
}
def SapiVoice {
# Define properties
$Speaker = New-Object -ComObject SAPI.SPVoice
$Message = 'Hello, World!'
$one = ""
$two = ""
# Define methods
function Say {
param([string]$text)
[void]$Speaker.Speak($text, 1)
}
function SayHello {
Say "$Message, $one, $two"
}
function Initialize {
param($first, $second)
$this.one = $first
$this.two = $second
}
# Now define what is public
Export-ModuleMember -Function Say,SayHello,Initialize
Export-ModuleMember -Variable One,Two
}
$sapiVoice = new SapiVoice 1 2
def SapiVoice { # opening the powershell 'class'
function SayGoodbye {
Say "Goodbye"
}
Export-ModuleMember -Function SayGoodbye
}
$sapiVoice2 = new SapiVoice 3 4
#$sapiVoice.SayGoodbye() # would error since it was created prior to being extended
$sapiVoice.SayHello()
$sapiVoice2.SayHello()
$sapiVoice2.SayGoodbye() # says goodbye
$sapiVoice2 | Get-Member -View Extended
TypeName: Prototype#SapiVoice
Name MemberType Definition
---- ---------- ----------
Initialize ScriptMethod System.Object Initialize();
Say ScriptMethod System.Object Say();
SayGoodbye ScriptMethod System.Object SayGoodbye();
SayHello ScriptMethod System.Object SayHello();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment