4

I am trying to create a custom object with custom method and key value pair inside that method in powershell.

$mymethod= @{
MemberName = "mymethod"
MemberType = 'ScriptMethod'
Value = {'Test'}
Force = $true
}
Update-TypeData -TypeName 'Dummy' @mymethod
$test = [PsCustomObject][Ordered]@{PsTypeName = 'Dummy'}

So this creates and object like $test.mymethod() with the value "Test"

What I am trying is to create like below:

    $test.mymethod('key1')='value1'
    $test.mymethod('key2')='value2'

Any help?

3
  • 1
    PowerShell 5+ has class which would enable you to create instance objects with methods. What is the output of $PSVersionTable.PSVersion? Commented Aug 2, 2018 at 18:18
  • 2
    Looks to me like what you actually want isn't a method, but a property that is a hashtable: $test = [PSCustomObject]@{'foo' = @{}}; $test.foo['key1'] = 'value1'. Commented Aug 2, 2018 at 19:01
  • 1
    As an aside: you don't need the [ordered] before the hashtable literal (@{ ... }) that you cast to [pscustomobject], because [pscustomobject] { ... } is syntactic sugar that implicitly preserves the key-definition order in the resulting object's ordering of properties. Commented Aug 2, 2018 at 20:14

2 Answers 2

3

To answer the question generically (even though the specific use case may warrant a simpler solution, as demonstrated in TheIncorrigible1's answer):

Note: In the code below I'm assuming that by $test.mymethod('key1')='value1' you actually meant to say that you want $test.mymethod('key1') to return 'value1', given that using a method call as the LHS of an assignment doesn't make sense.


lit mentions a PSv5+ alternative: defining a [class]:

# Define the class.
class Dummy { 
 [string] mymethod([string] $key) { return @{ key1='value1'; key2='value2' }[$key] }
}

# Instantiate it
$test = [Dummy]::new()

# Call the method
$test.mymethod('key2') # -> 'value2'

If you do want to use PowerShell's ETS (extended type system), as in your question (which is your only option in PSv4-, short of embedded C# code via Add-Type):

Perhaps the only hurdle was not knowing how to define a parameter for the method (use a param() block) and possibly how to access the instance on which the method is invoked (use $this); both techniques are demonstrated below:

# Define a type named 'Dummy' and attach a script method named 'mymethod'
$mymethod = @{
  MemberName = 'mymethod'
  MemberType = 'ScriptMethod'
  # Note the use of param() to define the method parameter and
  # the use of $this to access the instance at hand.
  Value      = { param([string] $key) $this.Dict[$key] }
  Force      = $true
}
Update-TypeData -TypeName 'Dummy' @mymethod

# Create a custom object and give it an ETS type name of 'Dummy', which
# makes the mymethod() method available.
$test = [PsCustomObject] @{ PsTypeName = 'Dummy'; Dict = @{ key1='value1'; key2='value2' } } 

$test.mymethod('key2')  # -> 'value2'
Sign up to request clarification or add additional context in comments.

Comments

1

To expand on @Ansgar Wiechers's comment, it sounds like you're trying to recreate a dictionary, of which .NET has plenty:

$test = [pscustomobject]@{
    bar = [ordered]@{
    }
}

In action:

$test.bar.Add('key1', 'value1')
$test.bar.Add('key2', 'value2')

Output:

> $test
>> bar
>> ---
>> {key1, key2}

> $test.bar
>> Name    Value
>> ----    -----
>> key1    value1
>> key2    value2

1 Comment

As a footnote, @{} is a literal hashtable, which is just another key/value dictionary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.