I would like to create a custom dictionary class in PowerShell (which temporary stores a configuration in a specific 3rd party application and retrieves it in another PowerShell session). Technically, I could also do this by creating a kind of Set-MyConfigVariable -Key <key> -Value <Value> and Get-MyConfigVariable -Key <key> cmdlets, but I would like to investigate if I can make in more user (author) frindly with a extended dictionary (and hook in the getterand setter methods).
In short, something that is discribed here in C#: How to write a getter and setter for a Dictionary?
Class MyStore: System.Collections.Generic.Dictionary[String,String] {
$h = @{}
[string]$This([String]$Key) {
get { write-host 'getting something'; return $h[$Key] }
set { write-host 'setting something'; $h[$Key] = $Value }
}
}
$MyStore = [MyStore]::new()
$MyStore['key'] = 'value'
$MyStore['key']
The above prototype fails at [string]$This([String]$Key) { (the indexer?) but probably also need a different implementation for the getter and setter (using Update-TypeData?).
How can this be done in PowerShell (if even possible)?
If not possible for a class, can it be done on an single instance (with dynamic keys)?
PowerShell code, using custom
classes, has the following limitations as of PowerShell 7.3.4:There's generally no support for property getters and setters - GitHub issue #2219 proposes adding support for them.
For now, getters and setters for regular properties can be emulated, using
Add-Memberwith aScriptPropertymember, as shown in this answer.Tip of the hat to Santiago Squarzon.However, there is no workaround for implementing parameterized properties, as is required for implementing indexers.
C# code, ad hoc-compiled with
Add-Type, offers a solution:Deriving your custom class from
Dictionary[String,String]- as you've attempted - is problematic, because it requires hiding the base class members with thenewkeyword, which in PowerShell code - at least as of PowerShell 7.3.4 - isn't fully supported - see GitHub issue #19649.However, you can make your custom class wrap a dictionary type, and provide access to it via type-specific indexer (parameterized property), into which you can hook PowerShell script blocks to execute.
See the following sample implementation:
Output:
Note: