Last active
February 28, 2019 04:52
-
-
Save jakobii/eec3d56dc7a5492b1c87f6ba4b8b96d4 to your computer and use it in GitHub Desktop.
Embed C# In Powershell And Define Custom Interfaces!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # here is our custom interface. hopefully powershell will support creating | |
| # interfaces natively soon. this is a simple example and is not ment to | |
| # teach you c# syntax. sufice it to say an interface is a *contract*. an | |
| # interface defines what methods and properties a class should have. | |
| # interfaces allow you to contrain function parameters to only type that | |
| # fullfill the *contract*. this is illistrated in the code below. | |
| $CSharpCode = @" | |
| public interface IFoo | |
| { | |
| void Bar(); | |
| } | |
| "@ | |
| # compile the C# and make the code available in our powershell run time. | |
| Add-Type -TypeDefinition $CSharpCode -Language 'CSharp' -Verbose | |
| # define a function which will require that the agruments passed ot it | |
| # "fullfill" (aka "Implement") the [IFoo] "contract" (aka "C# interface"). | |
| # we will do this by simple adding the [IFoo] type to one of our function | |
| # parameters. | |
| function test-foo ([ifoo]$i) { | |
| $i | gm | |
| $i.Bar() | |
| } | |
| # now we can create a type which implements our newly created | |
| # [IFoo] interface. we do this by defining our class [test1] | |
| # and giving it a base class of [IFoo] | |
| class test1 : IFoo { | |
| Bar() { | |
| Write-Host "you just wrote some c# in powersell!" -f green | |
| Write-Host "[test1] Implements [IFoo]" -f green | |
| } | |
| } | |
| # to further illistrate the usefullness of interfaces let create a different | |
| # class that also implements the [IFoo] interface. also notice that we can | |
| # implement multiple interfaces by seperating them with comma's. | |
| class test2 : IFoo, system.IComparable { | |
| Bar() { | |
| Write-Host "hurray for abstraction!" -f green | |
| Write-Host "[test2] Implements [IFoo]" -f green | |
| } | |
| [int] CompareTo([object] $obj) { | |
| return 42; | |
| } | |
| } | |
| # while we are on the subject here are some things to keep in mind when it comes | |
| # to class inheritants in powershell. its is a convention to start interface | |
| # names with a capital "I". also powershell classes are only able to inherit the | |
| # from the first base class, but they can implement many interfaces. if thats | |
| # information went over your head, dont worry it not super important for this | |
| # example. lets keep going! | |
| # [test3] is an example of similar class, with the same method signature | |
| # as [test1] and [test2] but notice we are not adding the [IFoo] interface | |
| # this time. let see what happens. | |
| class test3 { | |
| Bar() { | |
| Write-Host "This Should fail" -f red | |
| } | |
| } | |
| # now lets test the function and make sure that only types that implement | |
| # our c# interface will work with our function. this should work becuase | |
| # [test1] implements [IFoo]. | |
| test-foo -i $([test1]::new()) | |
| # [test2] also works becuase it also implements the [IFoo] interface! | |
| test-foo -i $([test2]::new()) | |
| # our [test3] class does not implement our c# interface, so if everything | |
| # is working as expected this should fail and the catch{} block will run. | |
| try { | |
| test-foo -i $([test3]::new()) | |
| } | |
| catch { | |
| write-host '[test2] does not implement [IFoo]' -f green | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment