3 вопроса, каждый уместный ... возможно ли зациклить объявления функций, вызвать системные объекты и загрузить сборки из строк? - PullRequest
0 голосов
/ 22 июня 2019

У меня есть некоторые идеи, которые я считаю довольно классными, но я не знаю, как заставить все это работать ... Итак, я спрошу ...

У меня есть вопрос, и все они довольно похожи, поэтому у меня есть ощущение, что у них всех может быть один и тот же ответ, хотя я не уверен.

Я пытался использовать TypeDefinitions, Add-Type, New-Object и т. Д., Но ничего из этого не работает. Я возился с математикой ... и несмотря на все мои старания? До сих пор не понял, как заставить его работать. Я спросил коллег-программистов, но у них всех может быть неправильное представление о том, чего я пытаюсь достичь. Так что вот так ...

# Being able to call system objects, or system type objects from an array of common strings ( lets call each one it's own 'lego' ). #
# Instead of ... #
if ([ Security.Principal.WindowsPrincipal ][ Security.Principal.WindowsIdentity ]::GetCurrent()).IsInRole([ Security.Principal.WindowsBuiltInRole ]'Administrator')
{ execute the script... }

# You could do this...
$0 = "." , "Windows" , "Security" , "Principal" , "Identity" , "BuiltInRole"
$1 = -join $0[ 2 , 0 , 3 , 0 , 1 ]
$2 = $0[ 3..5 ] | % { New-Object $1 + $_ }
if (-join $2[0..1]::GetCurrent()).IsInRole($2[2])
{ execute script }
# Haven't gotten it working yet though, can't really call methods or types from a string as far as I know, but I know that SID strings are essentially calling types from a numerical index hence "S-1-5-21-...etc"


```

# Calling assemblies or assembly types from an array of strings (in the same manner as above for loading ASP.Net Assemblies - which are also system objects
# Example of how they're loaded now....
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.Linq ;
using System.Threading.Tasks ;
using Microsoft.AspNetCore.Mvc ;
using securedigitsplus.Models ;

# and how I'd like to load them in PowerShell and not even need the .cs files
$0 = "System" , ".Collections.Generic" ,  ".Diagnostics" , ".Linq" , ".Threading.Tasks" , "#etc.....#"
$1 = $0[0] , @( foreach ( $j in 1..4 ) | % { -join $0[0,$j] } )
0..$1.count | % { using ( New-Object or Add-Type -TypeDeclaration $_ I've tried both with no success... }

```

# Lastly... an example of redundant similar Function calls

Function Log-Message ( $MSG ) { $MSG | Out-File $LogFile -Append -Force }
Function Log-Console ( $MSG ) { Write-Host $MSG -F White  ; Log $MSG }
Function Log-Warning ( $MSG ) { Write-Host $MSG -F Yellow ; Log $MSG }
Function Log-Success ( $MSG ) { Write-Host $MSG -F Green  ; Log $MSG }
Function Log-Error   ( $MSG ) { Write-Host $MSG -F Red    ; Log $MSG }

# The idea to make it less redundant, create the same number of functions by looping the function declarations

$f = "Console" , "Warning" , "Success" , "Error"
$m = "White" , "Yellow" , "Green" , "Red"
0..4 | % `
{
    if ( $_ -eq 0 ) 
    {  
        Function Log { $MSG | Out-File $LogFile -Append -Force }
    }

    else
    { 
        Function "$( $f[$_] )" # I was thinking maybe Set-Variable ?
        {
            Write-Host $MSG -F $m[$_] ; Log $MSG
        }
    }
 }

Я надеюсь, что дал достаточно хорошее объяснение или примеры того, что я пытаюсь сделать. Общая идея заключается в том, что я хотел бы иметь возможность создавать CmdLetBinding () в цикле в какой-то момент, особенно если есть несколько похожих, и DefaultParameterSetName, кажется, не является хорошим решением, но я Я только сейчас собираюсь сделать это с помощью простых функций / переключателей.

Если кто-то думает, что «вы пытаетесь изобрести колесо здесь» ... Я думаю, в этом есть некоторая заслуга ... но, как я понимаю, «ничто не идеально, даже колесо, которое все остальные используют ... у вас есть идея, которая хочет расти. Спросите кого-то, кто может помочь сделать это.

  • MC

1 Ответ

1 голос
/ 22 июня 2019

Вызов системных объектов из массива проиндексированных + объединенных строк

Если у вас есть .NET имена типов, хранящиеся в строках ,

  • приведен к [type] для преобразования их в объекты типа ; в PSv5 + вы можете вызывать статический ::new() метод для объектов такого типа, чтобы создавать экземпляров этого типа.

    • $typeName = 'System.DateTime'; $type = [type] $typeName; $instance = $type::new(0)
  • В качестве альтернативы (PSv4-) передайте строку имени типа в New-Object, чтобы создать экземпляр .

    • $typeName = 'System.DateTime'; New-Object $typeName -Args 0

Примечание. В обоих случаях вам необходимо знать соответствующие аргументы конструктора для передачи, если они есть.


Вызов сборок или типов сборок из массива строк

Ваш пример предполагает, что вы хотите импортировать пространства имен в ваш код , чтобы вам было удобнее ссылаться на типы по их имени (например, [Encoding]) вместо того, чтобы использовать полное имя типа (например, [System.Text.Encoding]), которое C # реализует как using <namespace>.

Эквивалентная функция PowerShell - using namespace <type-name>, но она работает только с литеральными именами типов (как в C #).

Кроме того, в отличие от литералов типа, таких как [Text.Encoding], пропуск компонента System является , а не необязательным, поэтому using namespace System.Text работает, но using namespace Text не работает (это спокойно принимается, но неэффективно).

Вы можете обойти это, используя Invoke-Expression (в противном случае следует избегать использования ):

$namespace = 'System.Collections'

Invoke-Expression "using namespace $namespace"

# Now you can access the types in namespace System.Collections by
# their mere name.
[ArrayList]  # short for: [System.Collections.ArrayList]

Пример избыточных аналогичных вызовов функций ... Идея сделать его менее избыточным

Похоже, вы пытаетесь определять функции динамически .

Поскольку функции PowerShell предоставляются как диск PowerShell с именем Function:, вы можете использовать Set-Content для динамического определения функций:

$f = "Console" , "Warning" , "Success" , "Error"
$m = "White" , "Yellow" , "Green" , "Red"

0..($f.Count-1) | ForEach-Object {

    if ( $_ -eq 0 ) {  
      Function Log { param($MSG) $MSG | Out-File $LogFile -Append -Force }
    }
    else {
      $funcName = $f[$_]
      Set-Content Function:$funcName @"
        param(`$MSG)
        Write-Host `$MSG -ForegroundColor $($m[$_])
        Log `$MSG
"@
    }

}

Это определит функцию Log и функции-оболочки Warning, Success и Error, которые предшествуют вызову Log с цветным выводом на консоль.

Обратите внимание на использование расширяемой here-string (@"<newline>...<newline>"@) для определения тела функции в виде многострочной строки (для удобства чтения) и на то, как встроенные символы $. это не должно быть расширено вперед, должно быть экранировано как `$.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...