Visual Studio ではワークスペースを使用して、[フォルダーを開く] 内のファイルのコレクションを表します。ワークスペースは IWorkspace 型で表されます。 ワークスペース自体では、フォルダー内のファイルに関連するコンテンツや機能は認識されません。 代わりに、他のユーザーが操作できるデータを生成して使用するための機能と拡張機能用の一般的な API のセットが提供されます。 プロデューサーは、Managed Extensibility Framework (MEF) を通じてさまざまなエクスポート属性を使用して構成されます。
ワークスペース プロバイダーとサービス
ワークスペース プロバイダーとサービスは、ワークスペースのコンテンツに対応するためのデータと機能を提供します。 コンテキスト ファイル情報、ソース ファイル内のシンボル、またはビルド機能が提供される場合があります。
どちらの概念も、ファクトリ パターン を使用し、ワークスペースによって MEF 経由でインポートされます。 すべてのエクスポート属性は IProviderMetadataBase
または IWorkspaceServiceFactoryMetadata
を実装しますが、エクスポートされた型には拡張機能で使用する必要がある具象型があります。
プロバイダーとサービスの違いの 1 つは、ワークスペースとの関係です。 ワークスペースには特定の種類のプロバイダーを多数含めることができますが、ワークスペースごとに作成されるサービスは特定の種類のサービスが 1 つだけです。 たとえば、ワークスペースには多くのファイル スキャナー プロバイダーがありますが、ワークスペースにはワークスペースごとに 1 つのインデックス作成サービスしかありません。
もう 1 つの重要な違いは、プロバイダーとサービスからのデータの使用です。 ワークスペースは、いくつかの理由からプロバイダーからデータを取得するためのエントリ ポイントです。 最初に、プロバイダーには通常、作成するデータの狭いセットがあります。 データは、C# ソース ファイルのシンボルまたは CMakeLists.txt
ファイルのビルド ファイル コンテキストである可能性があります。 ワークスペースは、コンシューマーの要求に応じて、その要求とメタデータが一致するプロバイダーを特定します。 第 2 に、多くのプロバイダーが要求に貢献できるシナリオもあれば、優先度が最も高いプロバイダーを使用するシナリオもあります。
これに対し、拡張機能はワークスペース サービスのインスタンスを取得し、直接操作できます。 IWorkspace
の拡張メソッドは、visual Studio によって提供されるサービス (GetFileWatcherServiceなど) で使用できます。 拡張機能は、拡張機能内のコンポーネントや他の拡張機能が利用できるワークスペースサービスを提供することがあります。 コンシューマーは、GetServiceAsync または IWorkspace
型で指定する拡張メソッドを使用する必要があります。
警告
Visual Studio と競合するサービスを作成しないでください。 予期しない問題が発生する可能性があります。
ワークスペース閉鎖時の処分
ワークスペースの終了時には、エクステンダーが破棄を実行し、非同期コードを呼び出さなければならない場合があります。 IAsyncDisposable インターフェイスを使用すると、このコードを簡単に記述できます。
関連する型
- IWorkspace は、開いているフォルダーのような開かれたワークスペースの中央エンティティです。
- IWorkspaceProviderFactory<T> は、インスタンス化されたワークスペースごとにプロバイダーを作成します。
- IWorkspaceServiceFactory は、インスタンス化されたワークスペースごとにサービスを作成します。
- IAsyncDisposable は、破棄中に非同期コードを実行する必要があるプロバイダーとサービスに実装する必要があります。
- WorkspaceServiceHelper は、既知のサービスまたは任意のサービスにアクセスするためのヘルパー メソッドを提供します。
ワークスペースの設定
ワークスペースには、ワークスペースを簡単かつ強力に制御する IWorkspaceSettingsManager サービスがあります。 設定の基本的な概要については、「ビルドタスクとデバッグタスクをカスタマイズする」を参照してください。
ほとんどの SettingsType
の種類の設定は、VSWorkspaceSettings.json
や tasks.vs.jsonなどの .json
ファイルです。
ワークスペース設定の機能は、ワークスペース内の単なるパスである "スコープ" を中心にしています。 コンシューマーが GetAggregatedSettingsを呼び出すと、要求されたパスと設定の種類を含むすべてのスコープが集計されます。 スコープ集計の優先順位は次のとおりです。
- "ローカル設定" (通常はワークスペース ルートの
.vs
ディレクトリ)。 - 要求されたパス自体。
- 要求されたパスの親ディレクトリ。
- ワークスペースのルートまでの (自身を含む) すべての親ディレクトリ。
- "グローバル設定"。ユーザー ディレクトリ内にあります。
結果は、IWorkspaceSettingsのインスタンスです。 このオブジェクトは、特定の型の設定を保持し、string
として格納されているキー名を設定するためにクエリを実行できます。 GetProperty メソッドと WorkspaceSettingsExtensions 拡張メソッドは、呼び出し元が要求される設定値の型を認識することを想定しています。 ほとんどの設定ファイルは .json
ファイルとして保持されるため、多くの呼び出しでは、これらの型の string
、bool
、int
、配列が使用されます。 オブジェクト型もサポートされています。 このような場合は、IWorkspaceSettings
自体を型引数として使用できます。 例えば:
{
"intValue": 1,
"stringValue": "s",
"boolValue": true,
"stringArray": [
"s1",
"s2"
],
"nestedIWorkspaceSettings": {
"nestedString": "ns"
}
}
これらの設定がユーザーの VSWorkspaceSettings.jsonにあると仮定すると、データには次のようにアクセスできます。
using System.Collections.Generic;
using Microsoft.VisualStudio.Workspace;
using Microsoft.VisualStudio.Workspace.Settings;
private static void ReadSettings(IWorkspace workspace)
{
IWorkspaceSettingsManager settingsManager = workspace.GetSettingsManager();
IWorkspaceSettings settings = settingsManager.GetAggregatedSettings(SettingsTypes.Generic);
// result == WorkspaceSettingsResult.Success
WorkspaceSettingsResult result = settings.GetProperty("intValue", out int intValue);
result = settings.GetProperty("stringValue", out string stringValue);
result = settings.GetProperty("boolValue", out bool boolValue);
result = settings.GetProperty("stringArray", out string[] stringArray);
result = settings.GetProperty("nestedIWorkspaceSettings", out IWorkspaceSettings nestedIWorkspaceSettings);
result = nestedIWorkspaceSettings.GetProperty("nestedString", out string nestedString);
// Extension method alternative using default values.
int intValueOrDefault = settings.Property("intValue", /* default */ 42);
// Missing key. result == WorkspaceSettingsResult.Undefined
result = settings.GetProperty("missing", out string missing);
// Wrong type for a key. result == WorkspaceSettingsResult.Error
result = settings.GetProperty("intValue", out IWorkspaceSettings notSettings);
// Special ability to union "stringArray" across all scopes.
IEnumerable<string> allStringArray = settings.UnionPropertyArray<string>("stringArray");
}
手記
これらの設定 API は、Microsoft.VisualStudio.Settings
名前空間で使用できる API とは無関係です。 ワークスペース設定はホストに依存せず、ワークスペース固有の設定ファイルまたは動的設定プロバイダーを使用します。
動的設定の提供
拡張機能では IWorkspaceSettingsProvider を提供できます。 これらのメモリ内プロバイダーを使用すると、拡張機能で設定を追加したり、他の設定をオーバーライドしたりできます。
IWorkspaceSettingsProvider
のエクスポートは、他のワークスペース プロバイダーとは異なります。 工場はIWorkspaceProviderFactory
ではなく、特殊属性はありません。 代わりに、IWorkspaceSettingsProviderFactory を実装し、[Export(typeof(IWorkspaceSettingsProviderFactory))]
を使用します。
// Common workspace provider factory pattern
[ExportFeatureProvider(some, args, to, export)]
internal class MyProviderFactory : IWorkspaceProviderFactory<IFeatureProvider>
{
IFeatureProvider CreateProvider(IWorkspace workspace) => new Provider(workspace);
}
// IWorkspaceSettingsProvider pattern
[Export(typeof(IWorkspaceSettingsProviderFactory))]
internal class MySettingsProviderFactory : IWorkspaceSettingsProviderFactory
{
// 100 is typically the value used by built-in settings providers. Lower value is higher priority.
int Priority => 100;
IWorkspaceSettingsProvider CreateSettingsProvider(IWorkspace workspace) => new MySettingsProvider(workspace);
}
アドバイス
IWorkspaceSettingsSource
(IWorkspaceSettingsProvider.GetSingleSettings
など) を返すメソッドを実装する場合は、IWorkspaceSettingsSource
ではなく IWorkspaceSettings
のインスタンスを返します。 IWorkspaceSettings
は、一部の設定の集計時に役立つ詳細情報を提供します。
設定に関連する API
- IWorkspaceSettingsManager ワークスペースの設定を読み取って集計します。
- GetSettingsManager がワークスペースの
IWorkspaceSettingsManager
を取得します。 - GetAggregatedSettings は、すべての重複するスコープで集計された特定のスコープの設定を取得します。
- IWorkspaceSettings には、特定のスコープの設定が含まれています。
ワークスペースの推奨プラクティス
- 作成時に
Workspace
コンテキストを記憶するIWorkspaceProviderFactory.CreateProvider
または同様の API からオブジェクトを返します。 プロバイダー インターフェイスは、このオブジェクトが作成時に保持されていることを想定して記述されます。 - ワークスペース固有のキャッシュまたは設定を、ワークスペースの "ローカル設定" パスに保存します。 Visual Studio 2017 バージョン 15.6 以降の
Microsoft.VisualStudio.Workspace.WorkspaceHelper.MakeRootedUnderWorkingFolder
を使用して、ファイルのパスを作成します。 バージョン 15.6 より前のバージョンでは、次のスニペットを使用します。
using System.IO;
using Microsoft.VisualStudio.Workspace;
using Microsoft.VisualStudio.Workspace.Settings;
private static string MakeRootedUnderWorkingFolder(IWorkspace workspace, string relativePath)
{
string workingFolder = workspace.GetSettingsManager().GetAggregatedSettings(SettingsTypes.WorkspaceControlSettings).Property<string>("WorkingFolder");
return Path.Combine(workingFolder, relativePath);
}
ソリューション イベントとパッケージの自動読み込み
読み込まれたパッケージは、IVsSolutionEvents7
を実装し、IVsSolution.AdviseSolutionEvents
を呼び出すことができます。 これには、Visual Studio でフォルダーを開いたり閉じたりするイベントが含まれます。
UI コンテキストを使用して、パッケージを自動的に読み込むことができます。 値は 4646B819-1AE0-4E79-97F4-8A8176FDD664
です。
トラブルシューティング
SourceExplorerPackage パッケージが正しく読み込まれませんでした
ワークスペースの拡張性は MEF ベースであり、コンポジション エラーにより、Open Folder をホストしているパッケージの読み込みに失敗します。 たとえば、拡張機能が ExportFileContextProviderAttribute
を持つ型をエクスポートするが、型が IWorkspaceProviderFactory<IFileContextActionProvider>
のみを実装している場合、Visual Studio でフォルダーを開こうとしたときにエラーが発生します。
エラーの詳細については、%LOCALAPPDATA%\Microsoft\VisualStudio\16.0_id\ComponentModelCache\Microsoft.VisualStudio.Default.errで確認できます。 拡張機能によって実装された型に関するエラーをすべて解決してください。
関連コンテンツ
- ファイル コンテキスト - ファイル コンテキスト プロバイダーは、Open Folder ワークスペースのコード インテリジェンスを提供します。
- インデックス作成 - ワークスペースのインデックス作成では、ワークスペースに関する情報が収集され、保持されます。