PowerShell을 사용한 종속성 주입
Windows PowerShell에서 DI(의존성 주입)를 사용할 수 있습니까?
제 초기 실험은 그렇지 않다는 것을 시사합니다.CmdLet에서 Constructor Injection을 사용하려고 하면 자체 등록조차 되지 않습니다.다시 말해, 이것은 불가능합니다.
[Cmdlet(VerbsDiagnostic.Test, "Ploeh")]
public class PloehCmdlet : Cmdlet
{
public PloehCmdlet(IFoo foo)
{
if (foo == null)
{
throw new ArgumentNullException("foo");
}
// save foo for later use
}
protected override void ProcessRecord()
{
this.WriteObject("Ploeh");
}
}
기본 생성자를 추가하면 CmdLet을 등록하여 사용할 수 있지만 기본 생성자가 없으면 사용할 수 없습니다.
서비스 로케이터를 사용하여 종속성을 검색할 수 있다는 것을 알고 있습니다. 하지만 안티패턴이라고 생각하기 때문에 그런 식으로 가고 싶지는 않습니다.
PowerShell API에 WCF의 ServiceHostFactory와 유사한 'Factory' 후크가 있었으면 좋았을 텐데, 있다면 찾을 수 없습니다.
cmdlet 클래스의 인스턴스는 PowerShell에서 cmdlet을 사용할 때마다 빈 생성자에서 생성됩니다.PowerShell이 어떤 생성자를 선택할지 제어할 수 없기 때문에 제안하는 것을 직접적으로 수행할 수 없습니다(그리고 저는 당신이 왜 그렇게 하고 싶어하는지 상상하기가 정말 어렵습니다).그래서 이 질문에 대한 간단한 대답은 아니오입니다.
비슷한 효과를 얻기 위해 cmdlet 모양의 인터페이스(BeginProcessing/EndProcessing/ProcessRecord/StopProcessing 포함)를 만들고 실제 코드에 얇은 래퍼인 cmdlet 묶음을 채우는 데 사용할 수 있습니다.IMHO 이것은 너무 복잡한 접근 방식일 것입니다.
저는 당신이 왜 이것을 하려고 하는지 정말 이해할 수 없습니다.시나리오에 대해 좀 더 설명해 주시겠습니까?
PSCmdlet을 기본 클래스로 사용하려면 RunSpace를 실행해야 하며 문자열로 실행할 명령만 지정할 수 있습니다.예를 보려면 이 링크를 참조하십시오.
기본 클래스로 Cmdlet으로 다시 전환하고 Property injection을 사용하여 종속성을 설정했습니다.가장 깨끗한 해결책은 아니지만, 저에게는 효과가 있었습니다.기본 클래스로서의 Cmdlet의 좋은 점은 다음과 같이 유닛 테스트에서 직접 호출할 수 있다는 것입니다.
var cmdlet = new MyCmdlet {
Dependency = myMockDependencyObject
};
var result = cmdlet.Invoke().GetEnumerator();
Assert.IsTrue(result.MoveNext());
자동화 시작 시 확장하기
기본적으로 PSCmdlet(WriteObject, WriteError, WriteProgress 등)에 대한 작업을 정의하는 IV View 인터페이스가 있으며, 이를 통해 실제 Commandlet이 되는 View를 구현할 수 있습니다.
또한 실제 기능인 컨트롤러도 사용할 수 있습니다.생성자에서 컨트롤러는 IP 제공자(모킹하려는 IP 제공자)와 IV 보기를 수신합니다.공급자가 공급자에게 호출을 수행하고 결과를 IView에 기록합니다. IView(Powershell Commandlet)에 반영됩니다.
보기를 초기화하는 동안 컨트롤러를 생성하고 자체(IView) 및 공급자를 전달한 다음 컨트롤러에 대한 작업을 수행합니다.
이 접근 방식을 사용하면 Cmdlet은 비즈니스 로직을 수행하지 않는 얇은 계층이며 모든 것이 컨트롤러에 있으며 이는 테스트 가능한 구성 요소입니다.
여기에는 생성자 주입을 사용할 수 없지만 cmdlet 자체를 사용할 수 있습니다.초기화하도록 설정된 하나의 매개 변수에 대해 첫 번째 호출을 하고, 관련 정보를 현재 세션 상태로 저장한 다음, 이후 호출을 통해 저장된 값을 세션 상태에서 다시 가져오도록 합니다.
여서저는끈하사용다니습했나를기,▁string▁single다▁a라는 단일 문자열을 사용했습니다.message
저장된 값을 나타내지만 원하는 유형의 매개 변수를 얼마든지 가질 수 있습니다.
NB: 아래의 C#은 PowerShell로 포장되어 있으므로 PS에서 직접 전체를 테스트할 수 있습니다.
$cs = @'
using System.Management.Automation;
[Cmdlet(VerbsDiagnostic.Test, "Ploeh", DefaultParameterSetName = "None")]
public class PloehCmdlet : PSCmdlet
{
const string InitialiseParameterSetName = "Initialise";
const string MessageVariable = "Test_Ploeh_Message_39fbe50c_25fc_48b1_8348_d155cad99e93"; //since this is held as a variable in the session state, make sure the name will not clash with any existing variables
[Parameter(Mandatory=true, ParameterSetName = InitialiseParameterSetName)]
public string InitialiseMessage
{
set { SaveMessageToSessionState(value); }
}
protected override void ProcessRecord()
{
if (this.ParameterSetName != InitialiseParameterSetName) //do not run the cmdlet if we're just initialising it
{
this.WriteObject(GetMessageFromSessionState());
base.ProcessRecord();
}
}
void SaveMessageToSessionState(string message)
{
this.SessionState.PSVariable.Set(MessageVariable, message);
}
string GetMessageFromSessionState()
{
return (string)this.SessionState.PSVariable.GetValue(MessageVariable);
}
}
'@
#Trick courtesy of: http://community.idera.com/powershell/powertips/b/tips/posts/compiling-binary-cmdlets
$DLLPath = Join-Path $env:temp ('CSharpPSCmdLet{0:yyyyMMddHHmmssffff}.dll' -f (Get-Date))
Add-Type -OutputAssembly $DLLPath -Language 'CSharp' -ReferencedAssemblies 'System.Management.Automation.dll' -TypeDefinition $cs
Import-Module -Name $DLLPath -Force -Verbose
#demo commands
Test-Ploeh -InitialiseMessage 'this is a test'
Test-Ploeh
Test-Ploeh
Test-Ploeh -InitialiseMessage 'change value'
Test-Ploeh
Test-Ploeh
"NB: Beware, your value can be accessed / amended outside of your cmdlet: $Test_Ploeh_Message_39fbe50c_25fc_48b1_8348_d155cad99e93"
$Test_Ploeh_Message_39fbe50c_25fc_48b1_8348_d155cad99e93 = "I've changed my mind"
Test-Ploeh
출력 예제
VERBOSE: Loading module from path 'C:\Users\UserNa~1\AppData\Local\Temp\CSharpPSCmdLet201711132257130536.dll'.
VERBOSE: Importing cmdlet 'Test-Ploeh'.
this is a test
this is a test
change value
change value
NB: Beware, your value can be accessed / amended outside of your cmdlet: change value
I've changed my mind
언급URL : https://stackoverflow.com/questions/1945572/dependency-injection-with-powershell
'source' 카테고리의 다른 글
이 CSS는 어떻게 원을 생성합니까? (0) | 2023.08.22 |
---|---|
Spring Boot connect Mysql과 MongoDb (0) | 2023.08.22 |
파워셸 스크립트를 사용하여 두 폴더를 동기화하는 방법 (0) | 2023.08.22 |
MariaDB: 대량 삽입 작업을 활성화하는 방법 (0) | 2023.08.22 |
라디오 단추의 원 색 변경 (0) | 2023.08.22 |