2

Following on from my previous posting on how to implement the IContainer in structure map, I have hit what I hope is my last problem for a while.

How does one pass additional (non Structuremap injected) objects into a constructor?

Lets take the following from a sample console application I have for testing this stuff out.

static void Main(string[] args)
{
     _container = StructureMapConfig.GetContainer();
     _userService = _container.GetInstance<IUserService>();
}

This throws the following error because my constructor has the randomParam and structuremap has no idea how to fill the gap:

An unhandled exception of type 'StructureMap.StructureMapBuildPlanException' occurred in StructureMap.dll

Additional information: Unable to create a build plan for concrete type CommonServices.UserService

Constructor:

public UserService(IUserRepository userRepository, IStringService stringService, string randomParam)
{
    _userRepository = userRepository;
    _stringService = stringService;
}

In my registry I define my user service like so:

 this.For<IUserService>().Use<UserService>();

The question I have is how do I do this in the simplest way?

I found this link but can not see how to use the suggestions as I would have to make my calling class aware of the dependencies of the UserService. AS you can see some of those are Data layer items, and I do not want to tell my UI layer about them.

http://structuremap.github.io/resolving/passing-arguments-at-runtime/

Community
  • 1
  • 1
Morn
  • 191
  • 1
  • 4
  • 14
  • Unlike forum sites, we don't use "Thanks", or "Any help appreciated", or signatures on [so]. See "[Should 'Hi', 'thanks,' taglines, and salutations be removed from posts?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts). – John Saunders Jan 23 '15 at 02:22
  • Understood - have read the attached post. – Morn Jan 23 '15 at 07:27
  • The question is: what for kind of value is `randomParam'? Is it a configuration value from the configuration string, or is it something that can/should change during execution, or is this value request specific? – Steven Jan 23 '15 at 10:29
  • In my real world case its a POCO that holds certain config data. The sting here is a trivial example of the problem – Morn Jan 23 '15 at 17:42

1 Answers1

10

You should be able to target your parameter like so:

this.For<IUserService>().Use<UserService>().Ctor<string>("randomParam").Is("YourValue");

Whilst this will work, it's worth mentioning that if the parameter you're injecting is tied to any kind of business logic, configuration or even if it value's based on certain conditions then I would suggest creating a builder class that acts as a proxy (similar to this answer) and encapsulates the logic that decides the value of the string and inject that instead.

When injecting strings like this you have to be careful not to put your business logic in the wrong place.

Community
  • 1
  • 1
Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63
  • Hmm - so looks like i need to go for a proxy type implementation if I want to send extra things in the constructor. Good point about the buisness logic. Have you found the need to pass additional stuff in via the constructor in your daily work? In the case i am trying to solve I am beginning to think that the class should be sorting its self out rather having somthing passed in. – Morn Jan 23 '15 at 17:49
  • It all depends on what you're trying to inject really. If it's a simple string value then I'm generally quite happy to inject it as described above. However generally I don't like injecting plain strings and instead try and wrap them in a type so any changes don't involve changing the signature of my API. For instance, instead of injecting a connection string I would rather inject a connection manager type as my connection may not always be a simple string. What does your class do? – Joseph Woodward Jan 23 '15 at 19:56
  • Essentially i just need to get in a class which hilds some string properties. I will revisit my approach as I think there is a better way of achiving without the need to pass in. Regarding your code snippet. If thats in the registry file, how does one call that?? – Morn Jan 25 '15 at 18:12
  • It is the right answer but this answer does not work if my Class's constructor is taking more than 1 parameters of different types like MyClass(ILogger logger, ISqlDb db) – Ashish-BeJovial Apr 22 '19 at 08:54