Search code examples
c#dependency-injectioninversion-of-controlautofac

Passing parameters from composite root down the DI chain


I'm working on a project that has very little dependency injection and I'd like to start adding it incrementally.

To test it out, I would like to expose an API endpoint, take the parameters passed to the API method by the calling client, create the composition root and then pass the parameters down the chain. The IoC Container I'm using is Autofac.

The question I have is basically what is the best way to pass runtime parameters to the constructor (the parameters passed by the consumer of the API) of a resolved service from the composition root? Also let's say that each constructor takes the parameter passed to the API, how would I pass it the parameter down the chain through all the service's constructors?

The answers I'm seeing when searching for an answer involves passing a factory. So I'd have something like this:

class Example
{
    private readonly ISftpClientFactory _clientFactory;

    public Example(ISftpClientFactory injectedFactory)
    {
        _clientFactory = injectedFactory;
    }

    public void DoTheWork()
    {
        var client = _clientFactory.GetClient(host, userName, password, timeout);
    }
}

The problem with this answer is that I don't know the string parameters passed to GetClient in DoTheWork, it should be passed to this class through the constructor from the composition root which gets the parameters from the API method.

The other solutions I've seen with a factory always seem like I have the information available in a global store such as in a textbox or session. In my case I could save the parameters in another class and then create a factory to retrieve from that store and then pass that factory down but it seems like overkill and breaks encapsulation.

The question can be


Solution

  • The Composition Root should not have to deal with runtime data. It only deals with fixed configuration values and the construction of components. As described in more detail here, runtime data should 'flow' through the methods and properties of already instantiated object graphs:

    Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. Instead, let runtime data flow through the method calls of constructed object graphs.