5

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")
2
  • I like what you're getting at. I don't think what you're asking for is possible in pure PowerShell. Here's the best I know: powershellstation.com/2016/05/22/custom-objects-and-pstypename Commented Jun 8, 2016 at 1:24
  • The example I posted above pretty much covers all the rules. But I am sure there are some things that still need to be done to make it like a native Powershell object. Ah yes, your link for PSTypeName is good, it adds a type name so you can use format.ps1xml formats against them. I will add it to the above examples. Commented Jun 8, 2016 at 2:13

2 Answers 2

1
  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.

Sign up to request clarification or add additional context in comments.

4 Comments

When I was writing the question, I was looking for strongly-typed object properties. But you are correct, the best example above does prevent objects that can't be cast to this type from being assigned. I edited my question to be more specific. Thanks for the reply.
What is the actual question here? What does "Strongly-type object properties" mean exactly?
The question is how to better make a custom object purely in Powershell, one that acts just like a native powershell object. As for "Strongly-typed object properties", I am looking for objects with properties that cannot change type (see Weakly-Typed object properties examples above.)
You can't, unless you compile a class like in your first example, or (in version 5.0+) define a class and create a ::new() instance
0

This is the best way I have found to create an object in Powershell that is part of a namespace and covers all 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

Comments

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.