Resolve dynamic number of instances of a dependency

Dec 31, 2014 at 8:19 PM
Let's say I have the following classes:
public class Worker
{
    private readonly IProcessor processor;
    
    public Worker(IProcessor processor)
    {
        this.processor = processor;
    }
    
    public void Execute()
    {
        List<Data> data = null; // load data from database here in place of null
        this.processor.ProcessData(data);
    }
}
This is pretty straightforward. I would register Worker with the container and a concrete type for IProcessor. Container verification would work on everything.

Now let's say instead I have this class:
public class MultiWorker
{
    public void Execute()
    {
        IEnumerable<Data> dataItems = null; // load data from database here in place of null
        foreach(Data dataItem in dataItems)
        {
            // how to get a new processor here?
        }
    }
}
For the sake of argument, let's say that a new instance of processor must be created for each data item. (A more realistic case may be creating a dynamic number of user controls to display the data, but the same idea could be applied here.)

The only way I've found to do this and maintain the ability to verify the container is to create a factory class and interface (ProcessorFactory/IProcessorFactory) containing the dependencies of Processor and inject the factory into Worker. Is there a better way? This seems like a case where injecting a Func<IProcessor> would work well, but I don't want to have to explicitly register the Func<IProcessor> and I'd like for the container to still be able to verify Processor. Is creating the factory manually the only (or best) way to do this?

I saw the example on allowing for resolving Func<T> delegates through unregistered type resolution, but it doesn't seem to verify on through T.

Thanks.
Coordinator
Dec 31, 2014 at 9:28 PM
Edited Dec 31, 2014 at 9:29 PM
My first thought is you should use a delegate (a Func<IProcessor>) if you want a new instance for each dataItem. Registering a Func<IProcessor> would fail without an implementation for IProcessor, e.g. container.Register<IProcessor, Processor>(); so you do have verification of the Processor implementation.
public class Worker
{
    private readonly Func<IProcessor> processorFactory;
    
    public Worker(Func<IProcessor> processorFactory)
    {
        this.processorFactory = processorFactory;
    }
    
    public void Execute()
    {
        foreach(Data dataItem in dataItems)
        {
            this.processorFactory().ProcessData(dataItem);
        }
    }
}
If you feel that having to register a Func<> is an overhead you wish you didn't have then start a new discussion on adding a feature to Simple Injector for delegate auto registration :-)
Coordinator
Dec 31, 2014 at 10:01 PM
My first thought is to create a proxy class for IProcessor, because the fact that a new Processor is needed on each call is an implementation detail that should not concern Worker at all.

So instead of injecting a factory or delegate into Worker, you should simply inject an IProcessor and solve yhe problem inside your composition root; inside your DI configuration:
container.RegisterSingle<IProcessor>(new PrcessorProxy(() =>
    container.GetInstance<RealProcessorImpl>()));
Here the ProcessorProxy simply looks as follows:
class ProcessorProxy : IProcessor {
    Func<IProcessor> factory;
    public ProcessProxy(Func<IProcessor> f) {
        this.factory = f;
    }

    public void Process(Data data) {
        this.factory().Process(data),
    }
}