问题
I have added WebAPI to my stateful serive and want to access StateManager
from it (from outside of StatefulService
class implementation).
What is the best way to do it?
Currently I am using a small class for this:
internal static class InstanceAccessor
{
internal static StatefulService ActiveInstance { get; set; }
}
And put the value inside RunAsync method of the StatefulService
:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
InstanceAccessor.ActiveInstance = this;
...
回答1:
There's a sample project on Github that shows a simple way to do it using dependency injection.
回答2:
Your service will potentially have multiple concurrent calls accessing the shared instance, in your code it is possible (but slightly unlikely) that a request to the WebApi is executed before the RunAsync has set the instance. You could move the assignment to the .ctor of the Service. But, since it is only reads you will do to the shared instance you don't need to worry about conflicts after you have set the instance.
The problem with this solution is testability. If you want to write unit tests for your WebAPi it will have a hard dependency on the shared instance. See this answer for more on this: Unit testing with singletons
Another way that could work for you is to work with Dependency Injection and an IoC container. You can setup your WebApi controllers to be constructed by a container that has references to all dependencies (including your service). Setting up IoC and Dependency Injection for Service Fabric/WebApi can be done as described here https://stackoverflow.com/a/41980513/1062217. You just need to add a dependency on your StatefulService
in the controller .ctor
.
public SomeApiController(StatefulService service)
{
_service = service;
}
And register the service in the container
public WebApiService(StatefulServiceContext context)
: base(context)
{
Container = new TinyIoCContainer();
Container.Register<StatefulService>(this);
}
However, if it is just the Statemanager
you need in the WebApi controller, your implementation will be easier to test and maintain if you just take a dependency on the StateManager
:
public SomeApiController(IReliableStateManagerReplica stateManager)
{
_stateManager = stateManager;
}
and register that in the service .ctor:
public WebApiService(StatefulServiceContext context)
: base(context)
{
Container = new TinyIoCContainer();
Container.Register<IReliableStateManagerReplica>(this.StateManager);
}
note, this example uses TinyIoC, but any IoC container would work
来源:https://stackoverflow.com/questions/42049901/access-azure-service-fabric-stateful-service-state