We are going to focus on three methods:
- AddToGroup
- AddGroupsFromEnum
- AddToBaseGroups
The other methods have been discussed at the beginning of this series here.
The Hidden attribute
Notice that AddToGroup and AddGroupFromEnum methods are hidden methods. Using the hidden keyword will hide the visibility when we do a get-member on our instance.
Keep in mind, that hidden properties and methods become visible when we pipe our class to get-member –force
Theoretically, in any other object-oriented language, we would have set the method to private. Private does not exists in Powershell (yet?), and the nearest thing to private would be hidden.
Why is it important to have hidden methods? Hidden is the only way we have to set a scope on properties or methods in powershell.
AddGroupsFromEnum
|
hidden [void]AddGroupsFromEnum([String]$GroupList){
$AllGroups = [System.Enum]::GetNames($GroupList)
foreach ($group in $AllGroups){
([Employee]$this).AddToGroup($group)
}
}
|
The AddGroupsFromEnum method takes a string as input. It will list all the values (names) that the enum contains, and call the addToGroup method with each element from the list. In our case, it happens to be the name of an AD group. It will then add our user to that specific group using “Add-ADGroupMember”.
|
hidden [void]AddToGroup([string]$AdGroup){
Add-ADGroupMember -Identity $Adgroup -Members (get-aduser $this.UserName)
}
|
Also, we have introduced in this version of the employee class the following property
|
hidden [String]$BaseGroupsEnumName
|
This property is important because it will contain the Enum name of our employee base type group,which will contain the list of Active directory groups we want to add to our user. The value is limited to be any string, but in our case, we it can be either InternalBaseGroups or ExternalBaseGroups.
For the polymorphism to work, it is important that the property BaseGroupEnumName is set in an inherited class, not in the Employee Class.
And finally the AddToBaseGroups method:
|
[void]AddToBaseGroups(){
$this.AddGroupsFromEnum($this.BaseGroupsEnumName)
}
|
This method is the key to our polymorphic approach of these classes. We can see, that the method AddToBaseGroups, will actually call another method named AddGroupsFromEnum . As we discussed above, this method requires a string represents the name of an existing Enum. To keep things dynamic, the value of this string is set in our child classes under the parameter called BaseGroupsEnumName (more about that in just a minute). Using this methodology, we can use the code of our parent class, no matter which child class will be calling this method. It is agnostic to the child type (it just has to be a child from Employee).
These were the important methods and properties for our polymorphism example. Now we will create two classes that inherit from our parent class Employee, : ExternalEmployee and InternalEmployee
ExternalEmployee and InternalEmployee classes
The code here under can be found under: Employee_Part5.ps1 on the github repository of this series.
ExternalEmployee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
Class ExternalEmployee : Employee{
ExternalEmployee([String]$FirstName,[String]$LastName){
$this.BaseGroupsEnumName = “ExternalBaseGroups”
$this.EmployeeType = [EmployeeType]::External
$this.FirstName = $FirstName
$this.LastName = $LastName
$this.UserName = [Employee]::GetNewUserName($FirstName,$LastName)
#Notice the call to our static property
$this.OU = “OU=$($This.EmployeeType),” + ‘OU=Users,OU=HQ,’ + [employee]::DomainName
}
}
|
InternalEmployee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
Class InternalEmployee : Employee{
InternalEmployee([string]$FirstName,[string]$LastName){
$this.BaseGroupsEnumName = “InternalBaseGroups”
$this.EmployeeType = [EmployeeType]::Internal
$this.FirstName = $FirstName
$this.LastName = $LastName
$this.UserName = [Employee]::GetNewUserName($FirstName,$LastName)
$this.OU = “OU=$($This.EmployeeType),” + ‘OU=Users,OU=HQ,’ + [employee]::DomainName
}
}
}
|
Both classes are similar. They contain only one single constructor accepting two strings (FirstName and LastName). In the end, they just inherit everything from their parent class Employee. They have the same set of properties and methods as their parent class Employee.
Note: When you use inheritance, the parent class (in our case, Employee) must have a parameter-less constructor declared (it can be left empty). Otherwise you won’t be able to instantiate your class.
Property wise, each implementation has three new properties, which will have another value depending in which class it is located. The properties are:
- EmployeeType
- OU
- BaseGroupEnumName
The PowerShell Polymorphism approach
The baseGroupEnumName is crucial in our case, because this is the link between all the classes, and binds the polymorphic approach of our solution.
Now that we have explained all the internal mechanism, we can create an instance of each, and compare the results.
To create an internal employee we will do as so:
|
$NewInternalEmployee = [InternalEmployee]::new(‘Stephane’,‘Van Gulick’)
$NewInternalEmployee.Create()
$NewInternalEmployee.AddToBaseGroups()
|
We can see that our user has been created in the internal OU, and that the groups that are listed in the InternalBaseGroups have been added to the user.
To create an External employee we will do as so:
|
$NewExtEmployee = [ExternalEmployee]::new(“Stephane”,“Van Gulick”)
$NewExtEmployee.Create()
$NewExtEmployee.AddToBaseGroups()
|
We can see that the user has been created in the External OU, and that the groups that are listed in the ExternalBaseGroups Enum have been added to the user. If the base groups of one of these type of users evolves, we can simply add or remove content into the appropriate Enum. It gives us flexibility, without changing any logic inside our code.
Notice how the both steps are identical. We set the values in each child class, and call inherited methods from our parent class, which actually use the properties that have been set in our child class (EmployeeType or OU for instance). We will be calling the same AddToBaseGroups method, and add our user to a different set of AD groups according to it’s type. This is how polymorphism works. And it is Awesome!
This was the end of my second series on powershell classes. I leave the intro section here again, so you can navigate easily to the next chapter you would like to read again.
This series has a total of 6 posts that covers everything that needs to be known about powershell classes. You will learn how to use powershell classes to manage your Active Directory going gradually through complex concepts until you are a pro with classes. I recommend you follow each step chronologically since we are building a class from bottom up and keep adding new blocks of code in each chapter. The complete
Quick reference:
- Introduction (here)
- Properties (here)
- Methods (here)
- Constructors (here)
- Inheritance (here)
- Polymorphism (here) This post
All the examples that are present on this page, and more globally throughout this series, are available on my github page here. (Exact reference to the file will be provided throughout the series).
Alternatively, I recommend you also read the other series I wrote on powershell classes. It will give you another concrete example, and walk you through some things that might not be fully covered in this series.
[…] Polymorphism (here) […]