VisualStudio.Extensibility SDK의 많은 구성 요소(예: 명령 처리기 및 도구 창 공급자)는 개별 클래스로 구현됩니다. 이러한 클래스 간의 구성 요소를 공유하기 위해 SDK는 .NET 종속성 주입 활용하여 필요에 따라 이러한 클래스를 인스턴스화합니다. 이러한 구성 요소 간의 데이터 공유를 간소화하기 위해 확장 개발자는 공유 구성 요소를 종속성 주입 그래프에도 기여하는 것이 좋습니다.
종속성 주입 그래프에 내부 서비스 추가
VisualStudio.Extensibility SDK의 각 확장에는 확장이 처음 로드될 때 만들어지는 고유한 서비스 그래프가 있습니다. 확장은 InitializeServices 메서드를 재정의하여 종속성 주입 그래프에 자체 서비스를 추가할 수 있습니다. 종속성 주입을 사용하여 서비스를 공유하는 예제는 Markdown Linter 참조할 수 있습니다.
메모
Visual Studio SDK의 IServiceProvider 패턴과 달리 이러한 서비스는 동일한 확장 내의 다른 구성 요소에만 표시되며 다른 확장과 공유되지 않습니다.
VisualStudio.Extensibility SDK에서 제공하는 서비스
확장에서 제공하는 서비스 외에도 VisualStudio.Extensibility SDK는 확장 인스턴스를 만들 때 그래프에 다음 서비스를 추가합니다.
TraceSource: 구성 요소가 경고 및 오류를 기록하는 데 사용할 수 있는 TraceSource의 공유 인스턴스가 그래프에 추가됩니다. 이러한 로그는 고객 보고서의 확장 문제를 진단하는 데 유용할 수 있습니다.VisualStudioExtensibility: 문서, 편집기, 작업 영역과 같은 Visual Studio와 상호 작용하도록 API를 노출하는 확장성 인스턴스입니다.
IServiceBroker: 서비스 브로커를 사용하여 Visual Studio 및 표면 영역에 포함되지 않을 수 있는 다른 서비스에서 제공하는VisualStudioExtensibility에 액세스할 수 있습니다.IServiceProvider: 서비스 공급자를 사용하여 확장의 자체 종속성 주입 그래프 내에서 서비스를 쿼리할 수 있습니다. 이 인스턴스는 In-process 확장에 대한 Visual Studio 프로세스의 전역 서비스 공급자와 동일한 인스턴스가 아닙니다.
프로세스 내 확장에 대한 추가 서비스
In-process를 실행하는 확장의 경우 다음 서비스도 사용할 수 있습니다.
JoinableTaskFactory및JoinableTaskContext: 다른 Visual Studio 서비스를 활용하는 in-process 확장으로 실행하는 경우 교착 상태를 일으키지 않고 이러한 인스턴스를 활용하여 주 스레드와 상호 작용해야 할 수 있습니다. 자세한 정보는 Visual Studio Threading cookbook를 참조하시기 바랍니다.asyncServiceProviderInjection 및 MefInjection: 이러한 클래스는 VisualStudio.Extensibility 확장 구성 요소의
IServiceProvider또는MEF인프라에서 제공하는 in-process 서비스를 검색하는 데 사용할 수 있습니다. 사용 가능한 경우 먼저 VisualStudio.Extensibility SDK에서 제공하는 서비스를 활용하는 것이 좋습니다.IAsyncServiceProvider2: 이 클래스는AsyncServiceProviderInjection메서드를 사용하여 in-process Visual Studio 서비스를 쿼리하는GetServiceAsync대신 사용할 수 있습니다.
VisualStudio.Extensibility SDK에서 제공하는 확장 메서드
IServiceCollection 인스턴스에 대한 확장 메서드를 사용하여 확장 기능과 관련된 서비스를 추가할 수도 있습니다.
- AddSettingsObservers: 확장이 SettingsCategory에 기여할 때 생성되는 이 메서드는,
InitializeServices에서 호출하여 기여한 설정 범주에 대한 관찰자 서비스를 삽입할 수 있습니다. SettingsSample 참조하여 사용 중인 이 메서드의 예를 확인할 수 있습니다.
서비스 수명
InitializeServices 메서드의 종속성 주입 그래프에 새 서비스를 추가하는 경우 세 가지 수명 옵션이 있습니다. 확장에서 다양한 수명 옵션을 사용하는 방법에 대한 예제 참조할 수도 있습니다.
AddSingleton: 이러한 서비스는 확장 인스턴스와 동일한 수명을 공유합니다. 대부분의 경우 Singleton 서비스를 사용하는 것이 VisualStudio.Extensibility SDK 확장에 적합한 선택입니다.AddTransient: 임시 서비스는 구현 클래스의 새 인스턴스를 만들거나 서비스에서 쿼리할 때마다 팩터리 메서드를 호출합니다. 결과적으로 각 구성 요소는 서비스의 자체 인스턴스를 가져옵니다.AddScoped: 이 범위는VisualStudioContribution특성 및 쿼리된 서비스가 있는 클래스에만 적용됩니다. VisualStudio.Extensibility SDK의 컨텍스트에서 범위는 기여된 구성 요소의 수명에 의해 정의됩니다. 대부분의 경우 이 수명은 확장 수명과 동일하므로 범위가 지정된 서비스와 싱글톤 서비스가 동일하게 작동합니다. 수명이 다른 기여된 구성 요소가 있는 경우 설명서에서 특별한 메모를 작성합니다.
예제 사용 사례
이 예제에서는 종속성 주입 및 InitializeServices사용하여 도구 창 구현과 명령 처리기 간에 공유 데이터 원본 개체를 사용하는 방법을 보여 줍니다.
MyExtension.InitializeServices에서MyDataSource은 구성 요소 간에 공유되는 싱글톤 서비스로 추가됩니다. 모든 도구 창 인스턴스에는 호스트된 컨트롤의 고유한 인스턴스가 있어야 하므로MyToolWindowControl임시로 추가됩니다.MyToolWindow에서는IServiceProvider의 조기 초기화를 피하기 위해, 필요할 때MyToolWindowControl를 통해 쿼리하도록 생성자에GetRequiredService을 삽입합니다.
[VisualStudioContribution]
public class MyExtension : Extension
{
protected override void InitializeServices(IServiceCollection serviceCollection)
{
// Always make sure to call the base method to add required services.
base.InitializeServices(serviceCollection);
serviceCollection.AddSingleton<MyDataSource>();
serviceCollection.AddTransient<MyToolWindowControl>();
}
}
[DataContract]
public class MyDataSource : NotifyPropertyChangedObject
{
}
public class MyToolWindowControl : RemoteUserControl
{
public MyToolWindowControl(MyDataSource dataSource) : base(dataContext)
{
}
}
[VisualStudioContribution]
public class MyToolWindow : ToolWindow
{
private readonly IServiceProvider serviceProvider;
public MyToolWindow(IServiceProvider serviceProvider)
{
}
public override Task<IRemoteUserControl> GetContentAsync(CancellationToken cancellationToken)
{
var control = this.serviceProvider.GetRequiredService<MyToolWindowControl>();
return Task.FromResult<IRemoteUserControl>(control);
}
}
[VisualStudioContribution]
public class MyCommand : Command
{
public MyCommand(MyDataSource dataSource) { }
}