Created
October 11, 2012 20:35
-
-
Save idavis/3875305 to your computer and use it in GitHub Desktop.
Mimicking ruby's open classes with PowerShell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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