views:

885

answers:

6

When I use another object in the .net-Framework in C# I can save a lot of typing by using the using directive.

using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It;

...


  var blurb = new Thingamabob();

...

So is there a way in Powershell to do something similiar? I'm accessing a lot of .net objects and am not happy of having to type

 $blurb = new-object FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob;

all the time.

A: 

This windows powershell blog posting has an example of how to achieve this

Colin Cassidy
While interesting, that blog entry discusses a lookalike for theusing statement (which in C# disposes a disposable after use), not the using directive for using a namespace.
froh42
That refers to the using statement (for IDisposable objects), not the using directive (for importing namespaces), as the OP wants.
Noldorin
+17  A: 

There's really nothing at the namespace level like that. I often assign commonly used types to variables and then instantiate them:

$thingtype = [FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob];
$blurb = New-Object $thingtype.FullName

Probably not worth it if the type won't be used repeatedly, but I believe it's the best you can do.

dahlbyk
+3  A: 

Check out this blog post from a couple years ago: http://blogs.msdn.com/richardb/archive/2007/02/21/add-types-ps1-poor-man-s-using-for-powershell.aspx

Basically what I do is crawl the assembly for nontrivial types, then write a "constructor" that uses Add-Member add them (in a structured way) to the objects I care about.

See also this followup post: http://richardberg.net/blog/?p=38

Richard Berg
A: 

this is just a joke, joke...

$fullnames = New-Object ( [System.Collections.Generic.List``1].MakeGenericType( [String]) );

function using ( $name ) { foreach ( $type in [Reflection.Assembly]::LoadWithPartialName($name).GetTypes() ) { $fullnames.Add($type.fullname); } }

function new ( $name ) { $fullname = $fullnames -like "*.$name"; return , (New-Object $fullname[0]); }

using System.Windows.Forms
using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It
$a = new button
$b = new Thingamabob

A: 

Thanks everybody for your input. I've marked Richard Berg's contribution as an answer, because it most closely resembles what I'm looking for.

All your answers brought me on the track that seems most promising: In his blog post Keith Dahlby proposes a Get-Type commandlet that allows easy consutruction of types for generic methods.

I think there is no reason against exetending this to also search through a predefined path of assemblies for a type.

Disclaimer: I haven't built that -- yet ...

Here is how one could use it:

$path = (System.Collections.Generic, FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It)

$type = get-type -Path $path List Thingamabob
$obj = new-object $type
$obj.GetType()

This would result in a nice generic List of Thingamabob. Of course I'd wrap up everthing sans the path definition in just another utility function. The extended get-type would include a step to resolve any given type agains the path.

froh42
+2  A: 

Here's some code that works in PowerShell 2.0 to add type aliases. But the problem is that it is not scoped. With some extra work you could "un-import" the namespaces, but this should get you off to a good start.

##############################################################################
#.SYNOPSIS
# Add a type accelerator to the current session.
#
#.DESCRIPTION
# The Add-TypeAccelerator function allows you to add a simple type accelerator
# (like [regex]) for a longer type (like [System.Text.RegularExpressions.Regex]).
#
#.PARAMETER Name
# The short form accelerator should be just the name you want to use (without
# square brackets).
#
#.PARAMETER Type
# The type you want the accelerator to accelerate.
#
#.PARAMETER Force
# Overwrites any existing type alias.
#
#.EXAMPLE
# Add-TypeAccelerator List "System.Collections.Generic.List``1"
# $MyList = New-Object List[String]
##############################################################################
function Add-TypeAccelerator {

    [CmdletBinding()]
    param(

        [Parameter(Position=1,Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [String[]]$Name,

        [Parameter(Position=2,Mandatory=$true,ValueFromPipeline=$true)]
        [Type]$Type,

        [Parameter()]
        [Switch]$Force

    )

    process {

        $TypeAccelerators = [Type]::GetType('System.Management.Automation.TypeAccelerators')

        foreach ($a in $Name) {
            if ( $TypeAccelerators::Get.ContainsKey($a) ) {
                if ( $Force ) {
                    $TypeAccelerators::Remove($a) | Out-Null
                    $TypeAccelerators::Add($a,$Type)
                }
                elseif ( $Type -ne $TypeAccelerators::Get[$a] ) {
                    Write-Error "$a is already mapped to $($TypeAccelerators::Get[$a])"
                }
            }
            else {
                $TypeAccelerators::Add($a, $Type)
            }
        }

    }

}
Josh Einstein
Josh, thanks I had not looked at extending the type accelerators, yet. This is very interesting, I think I'll play a bit around with it.
froh42
It's handy but use it with caution. Nothing worse than writing a script that doesn't work on someone else's machine. For that reason I never put these accelerators in my profile. If anything, I'll put them at the top of a script that way it'll fail at the Add-TypeAccelerator right away.
Josh Einstein