Home > OS >  Is there a way to add a method to built-in/native powershell object (or type?/class¿)?
Is there a way to add a method to built-in/native powershell object (or type?/class¿)?

Time:04-18

Is there a way to add a method to built-in/native powershell object (or type?/class¿)?

In particular, I'm looking at you [hashtable], but I suppose my question is also a general one... for instance, I could see wanting to add functionality to all my arrays...

For instance, I would like all my [hashtable] objects to have the method: .AddAndOverwrite(..) which would replace the value of the key if it exists; otherwise it creates a new key.

The only way I seem to be able to do this is to:

  1. create an empty hashtable, $HashTableNew
  2. add the ScriptMethod(s) to $HashTableNew (i.e. .AddAndOverwrite(..))
  3. then when I use it, make a copy of $HashTableNew
  • $SomeOtherHashTable = $HashTableNew.PSObject.Copy()

This just seems like not "the way"...

Note: I will admit, this is not the best example use of a data type extension method (as @SantiagoSquarzon points out)... but it is a simple one, and it allows for a simple example in the accepted answer; so I'm intentionally leaving it as is, rather than changing question / the extension method to .foo() returning widgets...

CodePudding user response:

There is indeed a better and easier way to update a type as a whole by using Update-TypeData.

Here is an example that add an .AddOrOverwrite method to the hashtable.

$TypeParam = @{
    TypeName = 'System.Collections.Hashtable'
    MemberType = 'ScriptMethod'
    MemberName = 'AddOrOverwrite'
    Value      = { Param($Key, $Value) $this.$key = $Value }
}

Update-TypeData @TypeParam -Force

$SomeHashTable.AddOrOverwrite('aaa','2222222')

$this, in the scriptblock of the method definition, correspond to the object reference that is targeted, in this case, the hashtable.

-Force will overwrite the definition every time without error stating the type was already added.

That method is not super useful as it does something that the hashtable manage pretty well on its own by just using assignment but it demonstrates how to do it.

Bonus example

Here's an example on how you would apply this principle and create 2 script properties (readonly) for a string so you can convert to base 64 back and forth.

$TypeParam = @{
    TypeName   = 'System.String'
    MemberType = 'ScriptProperty'
    Force = $true
}

Update-TypeData @TypeParam -MemberName 'Base64' -Value { [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($this)) }
Update-TypeData @TypeParam -MemberName 'Base64Decoded' -Value { [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($this)) }



# Encode the string to base 64 (Output: U29tZVN0cmluZw==)
"SomeString".Base64
# Decode the string from Base64 (Output: SomeString)
"U29tZVN0cmluZw==".Base64Decoded

References

Msdocs - About-Types

Dr Scripto - Easily Update Powershell Type Data by Using a Cmdlet

  • Related