Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining Custom Powershell Objects

There are many different ways to create objects in Powershell. I am posting this as a challenge to create objects purely in Powerhell. I am looking for a way to create objects using Add-Type that pass these requirements:

  1. Strongly-Typed object properties
  2. Instantiated, using: New-Object, [My.Object]::New(), [My.Object]@{'Property'='Value'}
  3. Part of a custom Namespace (i.e [My.Object])
  4. Can be type-checked. Example: $myVar -is [My.Object]

I know dll's can be created in Visual Studio that would accomplish this, but I am looking for a purely Powershell way to create objects.

Here is the closest example I have that satisfy the rules above:

PS C:\> $memberDef = @"
public String myString { get; set; }
public int myInt { get; set; }
"@

PS C:\> Add-Type -Namespace "My.Namespace" -Name "Object" -MemberDefinition $memberDef

PS C:\> $myObj = [My.Namespace.Object]@{'myString'='Foo'; 'myInt'=42}
PS C:\> $myObj

myString myInt
-------- -----
Foo         42

With that said, are there other (Possibly better) ways to create objects that look, feel, and act like native Powershell objects?

Examples that do not satisfy all rules

Weakly-Typed object properties:

PS C:\> $myObj = "" | Select-Object -Property myString, myInt

PS C:\> $myObj = New-Object -TypeName PSObject -Property @{'myString'='foo'; 'myInt'=42}


PS C:\> $myObj = @{}; $myObj.myString = 'foo'; $myObj.myInt = 42

PS C:\> $myObj.myInt = "This should result in an error."

Objects without namespaces:

PS C:\> $typeDef = @"
public class myObject {
   public string myString { get; set; }
   public int myInt { get; set; }
}
"@
PS C:\> Add-Type -TypeDefinition $typeDef
PS C:\> $myObj = [myObject]::new()

PS C:\> $myObj = New-Object -TypeName PSObject -Property @{'myString'='foo'; 'myInt'=42}
PS C:\> $myObj.PSObject.TypeNames.Insert(0, "myObject")
like image 749
B_Dubb42 Avatar asked Nov 09 '22 13:11

B_Dubb42


1 Answers

  1. Strongly-Typed object

The closest you're gonna get is an explicitly typed variable. This can be accomplished by casting the variable itself during assignment:

PS C:\> [My.Namespace.Object]$myObj = [My.Namespace.Object]@{'myString'='Foo'; 'myInt'=42}
PS C:\> $myObj = 123
Cannot convert the "123" value of type "System.Int32" to type "My.Namespace.Object".
At line:1 char:1
+ $myObj = 123
+ ~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

As you can see, this causes $myObj to only accept new assignments that can be implicitly converted to the type.

like image 122
Mathias R. Jessen Avatar answered Nov 15 '22 07:11

Mathias R. Jessen