14

Lets say we have a few interfaces defined in a .NET class library written in C#. Is there a way to implement these interfaces in a PowerShell script?

Call this a business need. We as a vendor, provide a few interfaces that are implemented by our customers to use our product. One of our customer wants to do this from PowerShell script.

Faisal
  • 4,054
  • 6
  • 34
  • 55
  • Why do you want to do this? PowerShell is dynamically typed itself. – poke Aug 18 '15 at 06:37
  • @poke don't see what this has to do with his question, implementing an interface doesn't have anything to do with powershell's typing, maybe he needs to pass his objects to a .net method that expects an IEnumerable for example – Ronan Thibaudau Aug 18 '15 at 06:40
  • @RonanThibaudau My question has to do with finding out about the [X of this Y](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – poke Aug 18 '15 at 06:44
  • @poke our customer wants to implement our interfaces in their PowerShell scripts. No one ever asked this before. – Faisal Aug 18 '15 at 06:48
  • 2
    possible duplicate of [Powershell. Create a class file to hold Custom Objects?](http://stackoverflow.com/questions/18705158/powershell-create-a-class-file-to-hold-custom-objects) – poke Aug 18 '15 at 06:50
  • related: [can INotifyPropertyChanged be implemented natively?](http://stackoverflow.com/q/21814444/33499) and [Does PowerShell support OOP?](http://stackoverflow.com/q/683811/33499) – wimh Aug 18 '15 at 06:50

3 Answers3

20

Here's a simple example with PowerShell 5.0 implementing the .Net IEqualityComparer interface:

Class A:System.Collections.IEqualityComparer {
  [bool]Equals($x,$y)  { return $x -eq $y        }
  [int]GetHashCode($x) { return $x.GetHashCode() }
}
[A]$a=[A]::new()
$a.Equals(1,1) -- returns True
$a.Equals(1,2) -- returns False
$a.GetHashCode("OK") -- returns 2041362128

You could even have a class (called A), which inherits from another class (called B) and implements IEqualityComparer:

Class A:B,System.Collections.IEqualityComparer {
Gnutella
  • 216
  • 1
  • 2
8

You can use Add-Type to define the class in C#, JScript, or VBScript. When there's a vendor-supplied assembly involved, it just has to be loaded prior to the Add-Type call, with another call to Add-Type:

$sourceCode = @"
    public class CustomerClass : Vendor.Interface
    {
         public bool BooleanProperty { get; set; }
         public string StringProperty { get; set; }
    }
"@    # this here-string terminator needs to be at column zero

$assemblyPath = 'C:\Path\To\Vendor.dll'
Add-Type -LiteralPath $assemblyPath
Add-Type -TypeDefinition $sourceCode -Language CSharp -ReferencedAssemblies $assemblyPath

$object = New-Object CustomerClass
$object.StringProperty = "Use the class"
JamesQMurphy
  • 4,214
  • 1
  • 36
  • 41
4

EDIT: It seems you can now implement interfaces in powershell 5.0. This answer applies to powershell 4.0 or earlier.

Although you cannot implement interface from powershell directly, you can pass powershell delegates to .NET code. You could provide empty implementation of interface accepting delegates in constructor, and construct this object from powershell:

public interface IFoo
{
    void Bar();
}

public class FooImpl : IFoo
{
    Action bar_;
    public FooImpl(Action bar)
    {
        bar_ = bar;
    }

    public void Bar()
    {
        bar_();
    }
}

And in powershell:

$bar = 
{ 
   Write-Host "Hello world!"
}

$foo = New-Object FooImpl -ArgumentList $bar
# pass foo to other .NET code
ghord
  • 13,260
  • 6
  • 44
  • 69