views:

100

answers:

3

Hi folks,

I've got a greedy constructor defined for my Controllers. Each controller requires an ILoggingService instance. Now my dependency injection (which is StructureMap .. but if you don't use that, please keep reading) works fine .. but I wish to make it that the ILoggingService greedy constructor requires a String. This value will be the fully qualified name of the Controller .. or some text (if that's too hard).

eg Current code..

public AccountController(IAccountService accountService,
    ILoggingService loggingService) { ... }

eg Wishful pseduo code...

public AccountController(IAccountService accountService,
    ILoggingService loggingService(this.GetType().ToString()
    .. or hardcod "X.Y..AccountController")
{ ... }

is this possible? I'm guessing I might have to define something tricky in the registry / bootstrap?

NOTE: I've tried using reflection but this doesn't work because the IoC uses an Instance Builder thingy which generates a unique object name for each injected instance.

Please help!

+1  A: 

Could you make ILoggingService a generic? Then you could request ILoggingService<AccountController>.

Your logging service could make use of it like so:

class LoggingService<T> : ILoggingService<T>{
   ...
   var thingName=typeof(T).ToString();
   ...
}
Josh Bush
A: 

You can't have a constructor on an interface at all.

One of the points of DI and loose coupling is that collaborators only know about each other through interfaces. How instances are created is of no concern to consumers.

You may have an implementation of ILoggingService that itself requires some dependencies, but that should be of no concern to the Controller - it must be able to work with any implementation of ILoggingService, or you would be breaking the Liskov Substitution Principle.

Sometimes, however, you need to communicate aspects about the consumer to the dependency, but this is better done as method parameters - e.g. you could pass the string in question as a parameter to the methods in the ILoggingService.

Mark Seemann
A: 

Inject logger factory ILoggerFactory, that you can ask for logger of some name: this.logger = _factory.GetLogger(GetType().Name()).

Notice that this is not IoC-specific solution. I'm not a big expert in IoC (though I use Windsor) so they may provide ways to do manual instantions. Something like

ioc.ForComponent(typeof(ILoggerService)).CustomInstantiate((type, desttype) => 
     Activator.CreateInstance(type, new object[]{desttype.Name}))
  • but of this I got no knowledge. Especially given that you want IoC to give you not only the type to create but also the type that is going to consume the instance.
queen3