How to pass state into a dependency chain using dependency injection

Viewed 2010

I have a number of service classes in a dependency chain (Service A depends on Service B, which depends on Service C etc.); their behaviors are determined by a common parameter (CountryCode), the possible supported country being defined at runtime.

Note: Actors can be scaled into multiple instances (different threads), and an event will only be processed by a single actor, services below are transient (although I can look into changing this if needed).

At the moment I have something like so:

//This application flow starts off with this class
public class ActorExample
{
    private IServiceOne _serviceOne; //Has dependent service

    public async Task ProcessAsync(Event event)
    {
        //This value needs to be passed to _serviceOne and any children
        //but we only know its value at runtime.
        event.CountryCode; 
    }
}

public class ServiceOne : IServiceOne
{
    private IServiceTwo _serviceTwo; //Has another nested dependency

    //Implementation here varies depending on event.CountryCode
    public async Task DoSomething()
}

public class ServiceTwo : IServiceTwo
{
    //Implementation here varies depending on event.CountryCode
    public async Task DoSomething()
}

I thought i could perhaps use generics with the services so passing the country code like so:

public class ServiceTwo<TCountryCode> : IServiceTwo<TCountryCode> 

But because we only have the value at runtime this is not possible, especially when injecting in the services.

Another solution is to inject the services with a dependent CountryCode as null and later populate in the constructors, something like:

container.Register(Component.For<IActor>().ImplementedBy<Actor>()
         .DependsOn(Dependency.OnValue("CountryCode", null));

however this seems messy and cumbersome especially if the nesting goes quite deep.

If all else fails i was perhaps considering setting the store before calling an functions but i would have to do this for every function eg:

_serviceOne.SetCountry(CountryCode).DoSomething();

Note: we are using castle for IOC

2 Answers
Related