Equivalente a la palabra clave "usando" de C#en PowerShell?
-
20-08-2019 - |
Pregunta
Cuando uso otro objeto en .NET-Framework en C#, puedo guardar mucho tipeo usando la directiva usando.
using FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It;
...
var blurb = new Thingamabob();
...
Entonces, ¿hay alguna manera en PowerShell para hacer algo similar? Estoy accediendo a muchos objetos .net y no estoy contento de tener que escribir
$blurb = new-object FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob;
todo el tiempo.
Solución
PowerShell 5.0 (incluido en WMF5 o Windows 10 y UP), agrega el using namespace
construir al idioma. Puedes usarlo en tu script así:
#Require -Version 5.0
using namespace FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It
$blurb = [Thingamabob]::new()
(Los #Require
La declaración en la primera línea no es necesaria para usar using namespace
, pero evitará que el script se ejecute en PS 4.0 y abajo donde using namespace
es un error de sintaxis).
Otros consejos
Realmente no hay nada a nivel de espacio de nombres como ese. A menudo asigno tipos de uso común a las variables y luego las instancias:
$thingtype = [FooCompany.Bar.Qux.Assembly.With.Ridiculous.Long.Namespace.I.Really.Mean.It.Thingamabob];
$blurb = New-Object $thingtype.FullName
Probablemente no valga la pena si el tipo no se usará repetidamente, pero creo que es lo mejor que puede hacer.
Mira esta publicación de blog de hace un par de años: http://blogs.msdn.com/richardb/archive/2007/02/21/add-types-ps1-poor-man-s-using-for-powershell.aspx
Aquí está add-types.ps1
, Extraído de ese artículo:
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
}
}
}
Y para usarlo:
RICBERG470> $tfs | add-types "Microsoft.TeamFoundation.VersionControl.Client"
RICBERG470> $itemSpec = new-object $tfs.itemspec("$/foo", $tfs.RecursionType::none)
Básicamente, lo que hago es rastrear el ensamblaje para los tipos no triviales, luego escribir un "constructor" que use Add-Member Agregarlos (de manera estructurada) a los objetos que me importan.
Vea también esta publicación de seguimiento: http://richardberg.net/blog/?p=38
Esto es solo una broma, broma ...
$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
Aquí hay algún código que funciona en PowerShell 2.0 para agregar alias de tipo. Pero el problema es que no está alcanzado. Con un poco de trabajo adicional, podría "no importar" los espacios de nombres, pero esto debería llevarlo a un buen comienzo.
##############################################################################
#.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)
}
}
}
}
Si solo necesita crear una instancia de su tipo, puede almacenar el nombre del espacio de nombres largo en una cadena:
$st = "System.Text"
$sb = New-Object "$st.StringBuilder"
No es tan poderoso como el using
Directiva en C#, pero al menos es muy fácil de usar.
Gracias a todos por su aporte. He marcado la contribución de Richard Berg como una respuesta, porque se parece más a lo que estoy buscando.
Todas tus respuestas me trajeron en la pista que parece más prometedor: en Su publicación de blog Keith Dahlby propone un comandro de tipo Get-Type que permite una fácil consución de tipos para métodos genéricos.
Creo que no hay razón en contra de exetender esto para buscar también a través de una ruta predefinida de ensamblajes para un tipo.
Descargo de responsabilidad: No he construido eso, todavía ...
Así es como uno podría 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()
Esto daría como resultado una buena lista genérica de Thingamabob. Por supuesto, concluiría todo sin la definición de ruta en solo otra función de utilidad. El tipo de Get-Type incluiría un paso para resolver cualquier tipo dado nuevamente la ruta.
#Requires -Version 5
using namespace System.Management.Automation.Host
#using module
Me doy cuenta de que esta es una publicación antigua, pero estaba buscando lo mismo y encontré esto: http://weblogs.asp.net/adweigert/powershell-adding-the-Using-statement
Editar: supongo que debería especificar que le permite usar la sintaxis familiar de ...
using ($x = $y) { ... }