WebApi 控制器访问其 StatelessService 实例

WebApi controller accessing its StatelessService instance

我正在使用一个实例在无状态服务中托管 WebApi 控制器。服务实例(我的意思是 SF 运行时创建的 WebApiService class 的实例)维护一些瞬时状态作为成员字段,通过内部(线程安全)方法公开状态。 WebApi 控制器需要调用方法来访问该状态。

WebApiService.cs:
-----------------
internal sealed class WebApiService : StatelessService
{
  private int _state;

  internal int GetState() { return this._state; }

ServiceController.cs:
---------------------
public class ServiceController : ApiController
{
  public async Task<IHttpActionResult> GetStateAsync()
  {
    // Here I'd like to grab somehow the WebApiService instance 
    // and call its GetState internal method.

我的问题是:

  1. 控制器如何获取对 WebApiService 实例的引用?

  2. 将 WebApiService 实例存储在静态字段中是否安全(可能在 WebAspiService 构造函数中设置)?

我认为您可以为此使用 DI 容器。我可以推荐 simpleinjector(但有很多可以做同样的事情),simpleinjector 也有每个请求的对象生命周期管理和一个 web api 包。您可以将您的状态实例作为单例放入容器中,并将其注入您的控制器中,这将是一种线程安全的方式,最好远离多线程网络环境中的静态字段。

在调用无状态服务的方法之前,您必须先在控制器中解析无状态服务:

public async Task<IHttpActionResult> GetStateAsync()
{
     var proxyLocation = new ServiceUriBuilder("WebApiService");
     var svc = ServiceProxy.Create<IWebApiService>(proxyLocation.ToUri());
     return svc.GetState();
}

您需要创建一个包含 GetState 方法的接口 IWebApiService。 WebApiService 需要实现它。基本上,您需要使用 IWebApiService 接口抽象 WebApiService。

通过 DI 容器将服务实例作为依赖项注入到您的控制器中。

这是一个使用 Unity 在 Katana 上托管 Web API 的示例。这是一个有状态服务,但它的工作方式与无状态服务完全相同:https://github.com/Azure-Samples/service-fabric-dotnet-getting-started/tree/master/Services/WordCount/WordCount.Service

这是一个使用 Asp.Net Core 及其内置依赖注入容器的示例(也是有状态的,但同样适用):https://github.com/vturecek/service-fabric-xray/tree/master/src/xray.Data