0

In this question: Examples of IoC Containers

There's an answer that warns that exceptions thrown in constructors are difficult to debug/handle, because the IoC eats them. A comment follows up to say that's no longer true.

How do .Net IoCs mitigate this flaw today, or are there some that still suffer here?

I'm interested in any .Net IoC that's used by at least 2 organizations (more than just you the author basically), but if you need a list: Windsor, StructureMap, Autofac, Ninject.

Community
  • 1
  • 1
Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
  • I'd keep this open, but IoC is simply a way of doing things, and what you're asking is implementation-specific; essentially, you're asking for a list of how implementations handle this (if they do indeed handle it this way). That said, you have a specific question about a specific IoC implementation, then that would be more constructive. – casperOne Sep 10 '12 at 19:54
  • 2
    @casperOne - Just my 2 cents but I think you're being a little heavy-handed with the Close link; while I understand why you've closed recent posts, people have deemed the questions worthy of an answer. You should give us a chance, IMHO, and if *we* think it's a bad question we have our own tools to indicate that to the community or moderators. kthx. – KeithS Sep 10 '12 at 20:09
  • 1
    We can't list how every container works. Simply decide which container you like and then do at test. It's like five lines of code to register a service in the container and then throw an exception during Resolve. – jgauffin Sep 11 '12 at 05:17
  • @jgauffin Well, many people will know one IoC in depth - many will know one or 2 off the top of their head, which is faster than one person building out 10 of those, or even better, faster than many people assessing IoCs that come and read this instead of building out 10 of those. – Chris Moschini Sep 11 '12 at 17:59
  • @ChrisMoschini: That's not the point. The test is simple to make. Pick your favorite container and test. Others have. – jgauffin Sep 11 '12 at 18:21
  • @jgauffin When you're considering the entire gamut of IoCs because you haven't chosen one yet, research like this is very helpful and saves not only me time, but others beginning the same choice. – Chris Moschini Sep 11 '12 at 19:00
  • @ChrisMoschini: Then use my container =) It got helpful exceptions. http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container – jgauffin Sep 11 '12 at 19:20

3 Answers3

3

Obviously this depends on the IoC container you are using. In my experience, rarely are exceptions "swallowed", they are reported at time of resolution. If you follow a common best practice of not doing anything other than accepting and verifying dependencies in your constructors then you should be fine.

Here's an example from unity:

void Main()
{
    IUnityContainer container = new UnityContainer();
    container.RegisterType<IAnimal, Dog>();

    // Exception thrown on this line
    var x = container.Resolve<IAnimal>();
}

public interface IAnimal
{
}

public class Dog : IAnimal
{
    public Dog()
    {
        throw new Exception();
    }
}

Reports this (which I think is very informative):

ResolutionFailedException: Resolution of the dependency failed, type = "UserQuery+IAnimal", name = "(none)".
Exception occurred while: Calling constructor UserQuery+Dog().
Exception is: Exception - Exception of type 'System.Exception' was thrown.
-----------------------------------------------
At the time of the exception, the container was:

Resolving UserQuery+Dog,(none) (mapped from UserQuery+IAnimal, (none))
Calling constructor UserQuery+Dog()
James World
  • 29,019
  • 9
  • 86
  • 120
  • So in the case of Unity, you wouldn't know the Exception occurred in the Constructor because the Container has it hidden, until you called x.Dump() to check on Exceptions - is that accurate? – Chris Moschini Sep 10 '12 at 19:54
  • No sorry, the exception is thrown on the call to Resolve... I just knocked this sample up in LinqPad and the Dump() is a utility function that gives debug info on variables. I cleaned up the sample a bit and removed that call to avoid confusion. – James World Sep 10 '12 at 20:03
1

I know for a fact that StructureMap will bubble up exceptions if they occur in the constructor, but there can be some weird nuances with this rule. For example, if you are using the SingletonPattern dispatcher and your assigned Singleton has crashed quietly earlier in the program's execution, StructureMap will happily input the crashed instance into anything that requests something of the singleton's type. At that point it's hard to tell what would happen, it all depends on how your program will handle accesses to the crashed instance.

But, as an example of something it will throw back at you, if you attempt to call an object's constructor with invalid or type-mismatched arguments, it will throw a descriptive error at the point the call is invoked. The setup will generally work fine, but you can test this ahead of time with the basic unit test (NUnit):

[Test]  
public void Assert_registry_is_valid()  
{  
    ObjectFactory.AssertConfigurationIsValid();  
}  

I certainly have never, ever, ever had problems with StructureMap swallowing errors. It is generally very easy to get helpful information and full stack traces out of it.

tmesser
  • 7,558
  • 2
  • 26
  • 38
1

I know that Autofac will "wrap" exceptions thrown out while trying to eagerly resolve dependencies. The InnerException of the AutofacException will be the exception that was thrown out by the constructor to the container. So, you generally handle resolution exceptions by catching AutofacExceptions and drilling into the InnerExceptions.

Most IoCs have "TryResolve"-like methods which gracefully return a true or false boolean, with an output parameter which is initialized if the resolution was successful. These methods are the ones that "eat" exceptions, and so if exceptions are useful to you, don't use these. Pretty much any call to the basic GetInstance or Resolve method that tries to produce a hydrated, constructor-injected object will throw out any exceptions that occur in the constructor chosen.

KeithS
  • 70,210
  • 21
  • 112
  • 164
  • Do you have a list of containers with this distinction in resolve calls? I see that Autofac and Windsor have TryResolve. Ninject has TryGet. StructureMap has TryGetInstance. Unity appears to not have this distinction, but a number of extension libraries implement it with wrappers and helpers. – Chris Moschini Sep 10 '12 at 20:06