Equivalente alla parola chiave "usando" di C#in PowerShell?
-
20-08-2019 - |
Domanda
Quando utilizzo un altro oggetto in .NET-Framework in C# posso salvare molta digitazione utilizzando la direttiva usando.
using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It;
...
var blurb = new Thingamabob();
...
Quindi c'è un modo in PowerShell per fare qualcosa di simile? Accedo a molti oggetti .NET e non sono felice di dover digitare
$blurb = new-object FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob;
tutto il tempo.
Soluzione
PowerShell 5.0 (incluso in WMF5 o Windows 10 e in su), aggiunge il using namespace
Costruire alla lingua. Puoi usarlo nella tua sceneggiatura in questo modo:
#Require -Version 5.0
using namespace FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It
$blurb = [Thingamabob]::new()
(Il #Require
L'istruzione sulla prima riga non è necessaria per l'uso using namespace
, ma impedirà allo script di funzionare in PS 4.0 e sotto dove using namespace
è un errore di sintassi.)
Altri suggerimenti
Non c'è davvero nulla a livello dello spazio dei nomi del genere. Assegno spesso i tipi comunemente usati alle variabili e quindi a istancio:
$thingtype = [FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob];
$blurb = New-Object $thingtype.FullName
Probabilmente non ne vale la pena se il tipo non verrà utilizzato ripetutamente, ma credo che sia il meglio che puoi fare.
Dai un'occhiata a questo post sul blog di un paio di anni fa: http://blogs.msdn.com/richardb/archive/2007/02/21/add-types-ps1 poor-man-s-using-for-powershell.aspx
Qui è add-types.ps1
, estratto da quell'articolo:
param(
[string] $assemblyName = $(throw 'assemblyName is required'),
[object] $object
)
process {
if ($_) {
$object = $_
}
if (! $object) {
throw 'must pass an -object parameter or pipe one in'
}
# load the required dll
$assembly = [System.Reflection.Assembly]::LoadWithPartialName($assemblyName)
# add each type as a member property
$assembly.GetTypes() |
where {$_.ispublic -and !$_.IsSubclassOf( [Exception] ) -and $_.name -notmatch "event"} |
foreach {
# avoid error messages in case it already exists
if (! ($object | get-member $_.name)) {
add-member noteproperty $_.name $_ -inputobject $object
}
}
}
E, per usarlo:
RICBERG470> $tfs | add-types "Microsoft.TeamFoundation.VersionControl.Client"
RICBERG470> $itemSpec = new-object $tfs.itemspec("$/foo", $tfs.RecursionType::none)
Fondamentalmente quello che faccio è strisciare l'assemblaggio per tipi non banali, quindi scrivere un "costruttore" che utilizza add-member aggiungendoli (in modo strutturato) agli oggetti a cui tengo.
Vedi anche questo post di follow -up: http://richardberg.net/blog/?p=38
Questo è solo uno scherzo, scherzo ...
$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
Ecco un codice che funziona in PowerShell 2.0 per aggiungere alias di tipo. Ma il problema è che non è scoperto. Con un po 'di lavoro extra potresti "non fare" gli spazi dei nomi, ma questo dovrebbe farti iniziare bene.
##############################################################################
#.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)
}
}
}
}
Se devi solo creare un'istanza del tuo tipo, puoi archiviare il nome dello spazio dei nomi lungo in una stringa:
$st = "System.Text"
$sb = New-Object "$st.StringBuilder"
Non è potente come il using
Direttiva in C#, ma almeno è molto facile da usare.
Grazie a tutti per il tuo contributo. Ho segnato il contributo di Richard Berg come risposta, perché assomiglia molto a quello che sto cercando.
Tutte le tue risposte mi hanno portato in pista che sembra più promettente: in Il suo post sul blog Keith Dahlby propone un comando di tipo get che consente una facile consursione di tipi per metodi generici.
Penso che non ci sia motivo di Exeting questo per cercare anche attraverso un percorso predefinito di assiemi per un tipo.
Disclaimer: non l'ho ancora costruito - ancora ...
Ecco come si potrebbe usarlo:
$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()
Ciò comporterebbe un bel elenco generico di ThingAmabob. Naturalmente avrei concluso tutto senza la definizione del percorso in un'altra funzione di utilità. Il tipo di getto esteso includerebbe un passaggio per risolvere un dato tipo di percorso.
#Requires -Version 5
using namespace System.Management.Automation.Host
#using module
Mi rendo conto che questo è un vecchio post, ma stavo cercando la stessa cosa e mi sono imbattuto in questo: http://weblogs.asp.net/adweigert/powershell-adding-the-using-statement
Modifica: suppongo che dovrei specificare che ti consente di utilizzare la sintassi familiare di ...
using ($x = $y) { ... }