Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap Specifying Explicit Constructor Arguments

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.

like image 874
Adam Rackis Avatar asked Aug 15 '11 21:08

Adam Rackis


1 Answers

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.

like image 86
Phil Sandler Avatar answered Nov 12 '22 19:11

Phil Sandler