Question:
I need to be able to have a class in powershell where I can create the names of the properties of that class dynamically. For example,
1 2 3 |
$binFiles = Get-ChildItem $files -Include *.BIN -recurse $binFiles.Name |
This would print something like:
File1.BIN
ThisFile.BIN
…
FileOther.BIN
I want these file names to be the names of the properties in my class that I will create multiple times. Is this even possible?
1 2 3 4 5 6 7 |
Class myItem { [String]$"File1.BIN" [String]$"ThisFile.BIN" .... [String]$"FileOther.BIN" } |
Answer:
You can use Invoke-Expression
(the solution is PSv5+, due to using custom PS classes):
1 2 3 4 5 6 |
Invoke-Expression @" Class myItem { $((Get-ChildItem $files -Include *.BIN -recurse).ForEach({"[string] `${$($_.Name)}`n "})) } "@ |
Note: While this particular use of Invoke-Expression
is safe, because you fully control the string being evaluated, Invoke-Expression
should generally be avoided.
The here-string produces the class definition as a string, which Invoke-Expression
then evaluates, which defines class [myItem]
for later use (e.g., $instance = [myItem]::new()
).
Note:
- The class definition statically creates properties based on the files present at the time you call
Invoke-Expression
. - Extending a class dynamically isn’t directly supported[1], but you can recreate the class later based on the then-current set of files, simply by repeating the
Invoke-Expression
call.[2]
The here-string produced above looks something like this – note the need to enclose the property names in {...}
, because they contain .
:
1 2 3 4 5 6 7 8 |
Class myItem { [string] ${File1.Bin} [string] ${File2.Bin} # ... } |
[1] A class is immutable once defined, although you could add properties dynamically to its instances using PowerShell’s ETS (extended type system), typically via the Add-Member
cmdlet.
Adding instance properties on demand would enable TheMadTechnician‘s suggestion of alternatively defining the class without properties and only an (instance) method that populates / updates a given instance’s properties on demand.
[2] Technically, the recreated class is a distinct .NET type, though that typically won’t matter, given that referring to it via a type literal – [myItem]
in this case – works the same.