3

我已将 WebAPI 添加到我的有状态服务中,并希望从中访问StateManager(从StatefulService类实现之外)。

最好的方法是什么?

目前我正在为此使用一个小班:

internal static class InstanceAccessor
{
   internal static StatefulService ActiveInstance { get; set; }
}

并将值放入 RunAsync 的方法中StatefulService

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    InstanceAccessor.ActiveInstance = this;
    ...
4

2 回答 2

2

您的服务可能会有多个并发调用访问共享实例,在您的代码中,有可能(但不太可能)在 RunAsync 设置实例之前执行对 WebApi 的请求。您可以将分配移至服务的 .ctor。但是,由于它只是读取您将对共享实例执行的操作,因此您无需担心设置实例后的冲突。

这个解决方案的问题是可测试性。如果你想为你的 WebAPi 编写单元测试,它将对共享实例有一个依赖。有关更多信息,请参阅此答案:Unit testing with singletons

另一种可能对您有用的方法是使用依赖注入和 IoC 容器。您可以将 WebApi 控制器设置为由引用所有依赖项(包括您的服务)的容器构造。可以按照此处https://stackoverflow.com/a/41980513/1062217中的描述为 Service Fabric/WebApi 设置 IoC 和依赖注入。StatefulService您只需要在控制器中添加对您的依赖项.ctor

 public SomeApiController(StatefulService service)
 {
     _service = service;
 }

并在容器中注册服务

public WebApiService(StatefulServiceContext context)
    : base(context)
{
    Container = new TinyIoCContainer();
    Container.Register<StatefulService>(this);
}

但是,如果它只是Statemanager您在 WebApi 控制器中所需要的,那么如果您只依赖于StateManager

 public SomeApiController(IReliableStateManagerReplica stateManager)
 {
     _stateManager = stateManager;
 }

并在服务 .ctor 中注册:

public WebApiService(StatefulServiceContext context)
    : base(context)
{
    Container = new TinyIoCContainer();
    Container.Register<IReliableStateManagerReplica>(this.StateManager);
}

请注意,此示例使用 TinyIoC,但任何 IoC 容器都可以使用

于 2017-02-05T09:12:36.223 回答
1

Github上有一个示例项目,它展示了一种使用依赖注入的简单方法。

于 2017-02-06T07:22:39.977 回答