代理服務要點
代理服務是透過 IServiceBroker 取得的服務,而且會公開為 RPC 相容的介面,讓服務及其用戶端存在於不同的 AppDomains、處理序或甚至跨機器 (在 Live Share 的情況下)。 代理服務可能會從主要 Visual Studio 程序或其一些輔助程序來提供,而且可由 Visual Studio 擴充功能取用這些程序。
更多 (非代理) Visual Studio 服務可透過 IServiceProvider 介面取得,如使用和提供服務中所述。 這類服務通常只能在主要 Visual Studio 程序中使用,但公開的功能集比代理服務更大。
在 Live Share 來賓上執行的 Visual Studio 擴充功能,可藉由存取 Live Share 主機所提供之這些服務的子集來提供其他功能。 授權檢查會透過 Live Share 連線套用,以降低行為不良的 Live Share 來賓危害 Live Share 主機安全性的風險。 選擇透過 Live Share 公開其服務的代理服務作者應該小心實作授權檢查,如如何提供代理服務中所述。
Service Broker
Visual Studio 有一個全域 IServiceBroker,類似於公開其他服務的 GlobalProvider,且可從中擷取。 它也可以透過 MEF 擷取。
特定 Visual Studio 功能可能會提供其他更多內容特定的 Service Broker,這些功能想要匯總全域服務代理程式,其中包含一個本身提供其他服務 (或可能隱藏某些服務)。
IServiceBroker是 (刻意) 一個黑箱,可讓用戶端取得可能位於本機、在另一個程序中或在另一部電腦上的服務。 Service Broker 可能是一或多個其他訊息的匯總,並套用原則。
根據 Visual Studio 程序所處的內容,此全域 Service Broker 是一組變更的其他代理服務匯總。 程序內的內容變更可能會變更可能啟動的一組代理服務。 例如,當解決方案載入與使用中解決方案特別相關的服務時,可能會變成可用狀態。 同一項服務也可在 [開啟資料夾] 檢視中取得,儘管有不同的備份實作。 服務實作中的變更對該服務的用戶端而言是透明的,因為這兩個實作都必須履行相同的合約,但用戶端必須在此內容變更中重新查詢服務 (透過 AvailabilityChanged 接收通知),才能取得新的執行個體。
Service Broker 通常用來取得服務的 Proxy。 也就是說,用戶端不直接接收服務物件的參考,而是接收虛設常式,該虛設常式會將所有方法呼叫轉送回服務,並將結果或例外狀況轉送回用戶端。 它也可能會將服務所引發的事件轉送至用戶端。 在某些情況下,服務可能會支援或要求用戶端提供服務可以叫用方法的「目標物件」,以回呼用戶端。
代理服務容器
服務必須提供給 IBrokeredServiceContainer,才能從全域 IServiceBroker 取得。 此服務容器不僅負責向 Service Broker 公開服務處理站,還負責控制哪些用戶端可以存取服務,以及在存取該服務時通知這些用戶端。
代理服務的組成
代理服務包含下列元素:
- 宣告服務功能的介面,並做為服務與其用戶端之間的合約。
- 該介面的實作。
- ServiceMoniker,可指派名稱和版本給服務。
- ServiceRpcDescriptor,結合 ServiceMoniker 與在必要時處理 RPC 的行為。
- 用來提供服務處理站的程式碼
- 服務註冊
服務介面
這可能是標準 .NET 介面 (通常以 C# 撰寫)。 若要允許代理服務用戶端和服務存在於不同的程序中,並透過 RPC 進行通訊,此介面必須遵守服務將使用之 ServiceRpcDescriptor 所指定的限制。 這些限制通常包括不允許屬性和索引器,而且大部分或所有方法都會傳回 Task 或其他非同步相容的傳回類型。
代理服務 Moniker 和描述項
啟用服務需要知道其 Moniker。 因為 Moniker 包含在服務的描述項中,用戶端通常只能處理 ServiceRpcDescriptor。 描述項會新增在代理服務與其用戶端之間設定 RPC 連線所需的行為,或當需要序列化往返 Stream 的 RPC 呼叫時。
Visual Studio 建議針對代理服務使用 ServiceJsonRpcDescriptor 衍生類型,以在用戶端和服務需要 RPC 進行通訊時,利用 StreamJsonRpc 程式庫。 StreamJsonRpc 會對服務介面套用某些限制,如這裡所述。
描述項很少需要直接使用。 相反地,通常會從 VisualStudioServices 或提供服務的程式庫取得,然後當作 GetProxyAsync 的引數使用。
ServiceMoniker 和 ServiceJsonRpcDescriptor 類別都是不可變的,因此可以安全地共用為 static readonly
欄位或屬性。
任何其他 ServiceRpcDescriptor 衍生類型都應該是不可變的。
ServiceMoniker 可序列化 。 ServiceJsonRpcDescriptor 無法序列化。
服務對象
每個代理服務都會註冊為從 ServiceAudience 選取的旗標。 這些旗標可控制哪些用戶端和代理服務將公開哪些連線。
典型的選取範圍是 ServiceAudience.Local,它會將服務公開至 Visual Studio 工作階段內的任何本機程序。 使用此設定時,服務一律會在本機啟動,即使 Live Shared 工作階段處於作用中狀態也一樣。
新增 ServiceAudience.LiveShareGuest 旗標時,要求代理服務的 Live Share 來賓會透過與 Live Share 主機的遠端連線,取得該代理服務的 Proxy。
ServiceAudience 上定義之旗標的任何組合都是合法的。 可以設定 LiveShareGuest 旗標 (而不需要也設定 Local 旗標),例如只向 Live Share 來賓公開代理服務 (來自 Live Share 主機),而且永遠不會在本機使用 (用戶端和服務位於相同程序中)。
RemoteExclusiveClient 和 RemoteExclusiveServer 旗標已被取代。
當用戶端要求代理服務時,它不需要知道該服務或服務將啟動的位置的 ServiceAudience 是什麼。 不過,對於記錄此值的服務,以及正在取用服務的開發人員,了解服務可能啟用的位置非常有用,這樣他們就可以預期來自該服務的各種內容,以及何時可以使用服務。
代理用戶端的組成
當用戶端要求代理服務時,當服務無法啟用、服務在啟用失敗時擲回 ServiceActivationFailedException,或取得服務的 proxy 時,就會取得 null
。
無論代理服務是在與用戶端相同的程序中啟動,還是使用不同的代理程式,都會使用 Proxy。
此 Proxy 有助於協調本機和遠端服務案例之間的使用模式,讓用戶端不需要知道服務所在的位置。