I’m working on legacy code.
I have different methods of the same class that pass different arguments to the constructor of a dependency. I’m trying to get some basic IoC usage introduced. Right now I have StructureMap passing my arguments like this:
var thing = ObjectFactory.GetInstance<IThingInterface>(new ExplicitArguments(
new Dictionary<string, object> {
{ "constructorArgA", notShown },
{ "constructorArgB", redacted.Property } }));
Where the actual properties passed for constructorArgA and B change depending on where I am.
Instead of “constructorArgA” is there a way to configure this via actual types, like you can do when configuring the objectFactory, like:
x.For<IHidden>().Use<RealType>()
.Ctor<IConfig>().Is(new Func<IContext, IConfig>(
(context) => someMethodToGetIConfig()));
If I were writing this from scratch I’d probably structure the dependencies a bit different to avoid this, but that’s not an option for me right now.
This is something of a classic/common question with DI Containers.
My first choice would be to create a “manual” abstract factory to create IThingInterface, and then use Structuremap to inject IThingInterfaceFactory where it is needed. By manual factory, I mean a class the calls new ThingInterface() and returns it. If you do it this way, your implementation will no longer be container-managed, and if it has dependencies, they would no longer be provided by the container (may or may not be a problem for you).
Second choice would be to create an abstract factory that actually uses/wraps the container. So basically your first code snippet but wrapped in a factory class where the Create() method takes your parameters. This has the advantage of everything (including your implementation and its dependencies) being container-managed, but the disadvantage of referencing your container directly (which is not a best practice–see Article on Composition Roots).
You could also do setter injection, but I would personally consider it a last resort.
Castle Windsor has a good solution to this problem built in (Typed Factory Facility). Not sure if switching containers in an option, but you might consider it.