Resolving Ambiguous Class Names Across PowerShell Modules

Right after my last post, I got to wondering what would happen if I had two modules with the same class named defined?

The dictionary defines ambiguous as “unclear or inexact because a choice between alternatives has not been made”. In context of this discussion, it means we have two different PowerShell modules that both have definitions for a class that is named the same (but may not necessarily look the same).

To quote one of the most often used phrases in technical blogging, “Let’s look at an example!”.

Here is our first module, which defines a class MyAmbiguousClass. As you can see it has one property and one method.

# MyAmbiguousModule1.psm1
class MyAmbiguousClass
{
  [string] $MyString = 'Ambigouous String 1'

  [string] GetSomeValue()
  {
    return 'Ambigouous Value 1'
  } 
}

Pretty simple. Now let’s look at a second module. This also has a class defined of MyAmbiguousClass, but it has two properties and one method, all with different names from the previous modules definition.

# MyAmbiguousModule2.psm1
class MyAmbiguousClass
{
  [int] $MyInteger = 2

  [string] $MyName = 'ArcaneCode'

  [string] DidILeaveTheStoveOn()
  {
    return 'Probably not'
  } 
}

You would then declare these at the top of your script thusly:

using module 'C:\PS\Classes and Modules\MyAmbiguousModule1.psm1'
using module 'C:\PS\Classes and Modules\MyAmbiguousModule2.psm1'

As described in my previous post, you would instantiate a new instace with this command:

$myClass = [MyAmbiguousClass]::new()

Now of course you can see the issue, it is not clear which version of the MyAmbiguousClass is being instantiated. What’s even scarier is PowerShell will execute this command without producing an error!

When PowerShell creates the new variable it looks through its memory to find the first time this class is defined, then it uses that definition. In this example, since the MyAmbiguousModule1.psm1 was loaded first, it is that definition that gets used.

If, however, the ‘using module’ statements had been reversed, and MyAmbiguousModule2.psm1 was first, then it is the definition for MyAmbiguousClass found in MyAmbiguousModule2.psm1 that would have been used.

Yikes!

So how to resolve? Well it turns out to be quite simple. All you have to do is prefix the class name with the module name, like so:

$myClass1 = [MyAmbiguousModule1.MyAmbiguousClass]::new()

Now intellisense will list the correct methods and properties, and we can access them in code.

$myClass1.MyString
$myClass1.GetSomeValue()

Will produce

Ambigouous String 1
Ambigouous Value 1

Likewise, we’ll prefix the second version with its module name, MyAmbiguousModule2:

$myClass2 = [MyAmbiguousModule2.MyAmbiguousClass]::new()
$myClass2.MyInteger
$myClass2.MyName
$myClass2.DidILeaveTheStoveOn()

Produces this output

2
ArcaneCode
Probably not

And there you go, resolving ambiguous class names across PowerShell modules is just that easy.

Advertisements

One thought on “Resolving Ambiguous Class Names Across PowerShell Modules”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s