views:

46

answers:

1

I am building an automation system using Powershell and I would like to define custom .Net types so that I can structure my application in a similar way to the other code I write.

At first, I tried using ‘Add-Type’ to import types from c# files into my application but I found this to be extremely painful to debug as a .net type can only be loaded once during per Powershell session. This means that when there are errors a single change to my code requires me to restart my app (I might as well be using C#).

At the moment I am simulating types in Powershell by using factory functions that dynamically generate PSObjects with the semantics I need. This does work but it is very verbose and I don’t seem to be able to declare private variables or methods for encapsulation.

Is there an easier way to achieve what I want?

If not....

Am I somehow barking up the wrong tree by wanting to write my Powershell code using abstract data types?

Is there a better way to structure my system that I should know about?

Can I achieve some encapsulation with what I am doing now?

+1  A: 

1) I haven't tried it, but this project looks promising: PSClass - Object Oriented Scripting in Powershell. Some features it offers:

PsClass is currently implemented in Powershell in a single file. Makes it simple to use. It supports the following OO concepts.

  • Inheritance
  • Polymorphism
  • Encapsulation
  • Constructors with parameters
  • Notes – read-write variables
  • Methods – scriptblocks
  • Properties with Get scriptblocks and optional Set scriptblocks
  • Static and Private Notes and Methods

2) You could use custom modules like this:

$o = New-Module -AsCustomObject -Function GetVar, AddToVar {
    $script:var = 1
    function checkRange { if ($var -gt 3 -or $var -lt 0) { throw 'not in range <0,3>' } }
    function GetVar { $script:var }
    function AddToVar { param($add) checkRange; $script:var += $add; $script:var }
}
$o.GetVar()
$o.AddToVar(2)
$o.AddToVar(1)
$o.GetVar()
$o.checkRange()
$o | gm

Try to copy it to your ide/console and run it. $script:var is private member that can be used only from functions GetVar,AddToVar. checkRange is private as well.


Personally I wouldn't use PowerShell for such a task if I needed real OOP (available in C#). PowerShell has some support for objects, but very poor for OOP.

stej
1+ thanks, I will look into thisLooks like Ruby + Python have the edge here, when it comes to dynamic scripting
Willbill
It depends on what you need, but if you really look for oop language, PowerShell is imho not a good choice. The target audience is other - mostly admin and power users, not programmers. But must be said, that it makes greaat job for programmers ;)
stej
I went down this route and the library is great. I did however run into some issues to do with trying to get -eq to work for my types and so on. I am working through these now.
Willbill