Visual Studio 문서 확장
문서는 Visual Studio에서 열린 파일의 메모리 내 표현입니다. 이를 moniker라고 하는데, 이는 file://
스킴을 이용한 절대적인 Uri
입니다. 문서는 다음과 같은 속성을 가진 DocumentSnapshot
클래스로 표시됩니다:
Moniker
IsDirty
IsReadOnly
IsInitialized
개체는 DocumentsExtensibility
개체 인스턴스를 가져오고 사용하는 DocumentSnapshot
데 사용되는 다양한 메서드를 제공합니다.
문서 작업
이 가이드는 문서 작업 시 주요 사용자 시나리오를 다루도록 설계되었습니다.
문서를 열기
디스크의 파일에 대한 경로를 고려할 때 Visual Studio에서 파일을 여는 것은 간단합니다.
DocumentsExtensibility documents = this.Extensibility.Documents();
Uri uri = new Uri(@"C:\path\to\Class1.cs", UriKind.Absolute);
DocumentSnapshot document = await documents.OpenDocumentAsync(uri, cancellationToken);
// optionally do something with the document
텍스트 문서 스냅샷 가져오기
A DocumentSnapshot
는 문서의 추상 표현입니다. 텍스트를 DocumentSnapshot
로 읽거나 쓰려면 ITextDocumentSnapshot
인터페이스를 사용할 수 있으며, 이는 DocumentSnapshot
의 AsTextDocumentAsync
확장 방법으로 얻을 수 있습니다.
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
DocumentsExtensibility documents = this.Extensibility.Documents();
Uri moniker = await context.GetSelectedPathAsync(cancellationToken);
DocumentSnapshot document = await documents.GetDocumentAsync(moniker, cancellationToken);
ITextDocumentSnapshot snapshot = await document.AsTextDocumentAsync(this.Extensibility, cancellationToken);
// insert the current date/time
EditorExtensibility editor = this.Extensibility.Editor();
using ITextViewSnapshot textView = await context.GetActiveTextViewAsync(cancellationToken);
await editor.EditAsync(
batch => snapshot.AsEditable(batch).Replace(textView.Selection.Extent, DateTime.Now.ToString()),
cancellationToken);
}
문서와 관련된 이벤트에 대응
구성 요소가 문서와 관련된 이벤트(즉, 열거나 닫거나 저장한 경우)에 반응할 수 있는 시나리오가 있습니다. 이 작업은 인터페이스를 구현하고 IDocumentEventsListener
이벤트 구독을 설정하는 데 사용하여 DocumentsExtensibility.SubscribeAsync
수행할 수 있습니다.
internal sealed class SubscribeCommand : Command, IToggleCommand
{
private IDisposable? subscription;
bool? IToggleCommand.IsChecked => this.subscription is not null;
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
if (this.subscription is null)
{
// subscribe for events
this.subscription = await Subscription.CreateInstanceAsync(this.Extensibility, cancellationToken);
}
else
{
// remove the event subscription
this.subscription.Dispose();
this.subscription = null;
}
this.OnPropertyChanged(new PropertyChangedEventArgs(nameof(IToggleCommand.IsChecked)));
}
private class Subscription : IDisposable, IDocumentEventsListener
{
private readonly OutputWindowExtensibility output;
private IDisposable? rawSubscription;
private Subscription(VisualStudioExtensibility extensibility)
{
this.output = extensibility.Views().Output;
}
public static async Task<Subscription> CreateInstanceAsync(
VisualStudioExtensibility extensibility,
CancellationToken cancellationToken)
{
var subscription = new Subscription(extensibility);
DocumentsExtensibility documents = extensibility.Documents();
subscription.rawSubscription = await documents.SubscribeAsync(subscription, filterRegex: null, cancellationToken);
return subscription;
}
public void Dispose()
{
this.rawSubscription?.Dispose();
this.rawSubscription = null;
}
Task IDocumentEventsListener.ClosedAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.ClosedAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.HiddenAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.HiddenAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.OpenedAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.OpenedAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.RenamedAsync(RenamedDocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.RenamedAsync ({e.OldMoniker} -> {e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.SavedAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.SavedAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.SavingAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.SavingAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
Task IDocumentEventsListener.ShownAsync(DocumentEventArgs e, CancellationToken token)
{
string text = $"IDocumentEventsListener.ShownAsync ({e.Moniker})";
return this.OutputEventTextAsync(text, token);
}
private async Task OutputEventTextAsync(string text, CancellationToken token)
{
using OutputWindow outputWindow = await this.output.GetChannelAsync(
identifier: "Document Sample Command Output",
displayNameResourceId: nameof(Strings.DocumentsSampleOutputWindowPaneName),
token);
await outputWindow.Writer.WriteLineAsync($"Event received: {text}");
}
}
}
다음 단계
- 이 시작 섹션에서 프로젝트 만들기 빠른 시작을 따릅니다.