Francesco B. Francesco B. - 1 year ago 111
C# Question

How to use Castle Windsor typed factory in this case?

Simple DI example:

public interface INumberToWordConverter
string ConvertNumber(int number);

public interface IOutputManager
void Write<T>(string who, T what);

public interface INumberProvider
int GenerateNumber();

public class PlayWithDI
private IOutputManager _outputManagerService;
private INumberProvider _numberProviderService;
private INumberToWordConverter _numberToWordConverterService;

private PlayWithDI() { }
public PlayWithDI(
IOutputManager outputManagerService,
INumberProvider numberProviderService,
INumberToWordConverter numberToWordConverterService)
if (outputManagerService == null)
throw new ArgumentNullException(nameof(outputManagerService));
if (numberProviderService == null)
throw new ArgumentNullException(nameof(numberProviderService));
if (numberToWordConverterService == null)
throw new ArgumentNullException(nameof(numberToWordConverterService));

_outputManagerService = outputManagerService;
_numberProviderService = numberProviderService;
_numberToWordConverterService = numberToWordConverterService;

public void Execute()
int number = _numberProviderService.GenerateNumber();
string wordOfNumber = _numberToWordConverterService.ConvertNumber(number);
_outputManagerService.Write(nameof(PlayWithDI), wordOfNumber);

Example implementations (just ctors):

// Implements INumberProvider
public RandomNumberProvider(
int min, int max,
IOutputManager outputManagerService)

// Implements INumberToWordConverter
public ItalianNumberToWordConverter(
IOutputManager outputManagerService)

// Implements IConsoleManager
public ConsoleOutputManager()

If I know which
give to
, I would just resolve like this:

public void Install(
IWindsorContainer container,
IConfigurationStore store)


Dependency.OnValue("min", 2),
Dependency.OnValue("max", 20)));


container.Install(new DependenciesConfiguration1());
var testDI = container.Resolve<PlayWithDI>();

The problem arises when I want to give custom parameters to
at runtime.

I took a look at
, but I don't really understand it in this example, because if I resolve a factory first, how should I then resolve PlayWithDi? Should I pass to its constructor an INumberProviderFactory instead of an INumberProvider?

In this case I thought about a factory like this:

public interface INumberProviderFactory
INumberProvider Create(
IOutputManager outputManager,
int min, int max);

When I'll then call
, how should I resolve the
then? I'm confused.

Answer Source

The problem arises when I want to give custom parameters to RandomNumberProvider at runtime.

This is where you go wrong. Injecting runtime data into components during construction is ananti-pattern:

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. [...] Let runtime data flow through the method calls of constructed object graphs.

In other words, your RandomNumberProvider should accept the min and max arguments is input parameters on the GenerateNumber method.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download