throwing rather than returning null

Oct 3, 2008 at 1:44 PM
Hi Guys - Really cool that most of the containers out there are willing to commit to a single interface. I really think this is a fair step forward.

I was wondering about one thing though, the specification states that an exception should be thrown if a service cannot be found/resolved, but doesnt provide any facility to test whether a service is available. For optional dependencies this means that i would have to catch the exception to know whether the dependency can be satisfied.

public TransactionManager(ILogger logger)
{
  this.logger = (logger == null)  ? new NullLogger() : logger;
  //a logger is optional, usage of the NullLogger is an implementation detail
}

right, you say inject them NullLoggers. Fair, but what if you want to version your service implementations independently of your contracts and container configuration. Which to me, is one of the key benefits of loose coupling.

public TransactionManager() //v1 contrstructor
  this:(null)
{
}

public TransactionManager(ILogger logger) //v2 contrstructor
{
  this.logger = (logger == null)  ? new NullLogger() : logger;
  //a logger is optional, usage of the NullLogger is an implementation detail
}

How would a DI Fx be able to figure out which contructor to choose without deliberately having to catch exceptions?
Perhaps I am missing the bigger picture here, I trust you guys had plenty of discussions on the topic of throwing exceptions and versioning.
Oct 3, 2008 at 7:30 PM

i would have to catch the exception to know whether the dependency can be satisfied.

Exactly.

This is off the top of my head, but I think you would do:

public TransactionManager() //v1 & v2 contrstructor
{
  IServiceProvider container = ServiceProvider.Current;
  try {
    this.logger = container.GetInstance<ILogger>();
  }
  catch (ActivationException ex)
  {
     this.logger = new NullLogger();
  }
}

 

However, in your example, there really isn't any need for the Common Service Locator.

Oct 3, 2008 at 7:54 PM
Hi Ray -

My example assumes a DI container to wire up the dependencies automatically.

And yes - I understand how this would work using a catch clause.... However I was more or less interested in the rationale behind this part of the spec, since if this indeed is considered a normal flow, throwing exceptions strikes me as somewhat odd.
Oct 3, 2008 at 8:02 PM
If you're using the DI to wire automatically, then you're not using the CSL.
Developer
Oct 3, 2008 at 9:51 PM
We debated back and forth about supplying an explicit "CanResolve" or something. Then somebody suggested that you could instead do GetAllInstances and if there's no registered service you'll get back a zero-length collection.
Oct 3, 2008 at 10:58 PM
Thanks Chris!