Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting the cause of a circular dependency in Unity

Is it possible to configure Unity to either detect a circular reference or to intercept the type resolver to display some debugging information?

Example

Here are a couple of interfaces and classes which are dependent upon each other

public interface IThing1 { }

public class Thing1 : IThing1
{
    private IThing2 _thing2;

    public Thing1(IThing2 thing2)
    {
        _thing2 = thing2;
    }

}

public interface IThing2 { }

public class Thing2 : IThing2
{
    private IThing1 _thing1;

    public Thing2(IThing1 thing1)
    {
        _thing1 = thing1;
    }
}

Castle Windsor

If these two types are configured in Castle Windsor it will throw an exception and provide some debug information to find the circular reference:

Castle.MicroKernel.CircularDependencyException: Dependency cycle has been detected when trying to resolve component 'CircularIoC.Thing1'.
The resolution tree that resulted in the cycle is the following:
Component 'CircularIoC.Thing1' resolved as dependency of
    component 'CircularIoC.Thing2' resolved as dependency of
    component 'CircularIoC.Thing1' which is the root component being resolved.

Unity

If Unity is configured to resolve these types like so

    private static void ResolveWithUnity()
    {
        var container = new UnityContainer();

        container.RegisterType<IThing1, Thing1>();
        container.RegisterType<IThing2, Thing2>();

        var thing = container.Resolve<IThing1>();

        container.Dispose();
    }

The call to container.Resolve<> will cause a StackOverflowException.

This is the documented behaviour but it would be nice to have some more useful information. Is there any customisation that will provide more information about the circular reference?

Alternatively is there any way to hook in to the type resolver process to emit some debugging information? I am thinking of decorating the main type resolver to output the name of the type being resolved. This will provide some feedback and a pointer to dependency that is causing the circular reference.

While I know that changing to a different IoC would solve the problem, this is not unfortunately an option.

like image 767
Keith Bloom Avatar asked Mar 19 '13 11:03

Keith Bloom


1 Answers

Unity sadly doesn't support this (incredibly important) feature. If you are willing to put your back into it, you can implement a smart decorator using some elbow grease.

What you will need is to override all Registration methods and build and update a data structure for the dependencies (dependency graph). Then write a method that preforms DFS to detect a circular dependency, you can either use it as a finalizer for the registration process, that will detect pre-resolving if circular dependencies are possible, or use it per resolve for the specific type requested.

As you can see, it's a lot of work...

Another option, is just to wrap up with a decorator the resolve methods and catch the StackOverflowException, analyze it to make sure it resulted from the resolving process, and build a proper circular dependency exception.

like image 76
JoefGoldstein Avatar answered Sep 28 '22 07:09

JoefGoldstein