Congenital Injection: Partially Initialized Object Injection

This question is about Unity Container, but I think it applies to any dependency container.

I have two classes with circular dependencies:

class FirstClass { [Dependency] public SecondClass Second { get; set; } } class SecondClass { public readonly FirstClass First; public SecondClass(FirstClass first) { First = first; } } 

It is technically possible to create and correctly enter dependencies for both of them, if we consider them as single ones:

 var firstObj = new FirstClass(); var secondObj = new SecondClass(firstObj); firstObj.Second = secondObj; 

When I try to do the same with Unity, I get a StackOverflowException:

 var container = new UnityContainer(); container.RegisterType<FirstClass>(new ContainerControlledLifetimeManager()); container.RegisterType<SecondClass>(new ContainerControlledLifetimeManager()); var first = container.Resolve<FirstClass>(); // StackOverflowException here! var second = container.Resolve<SecondClass>(); // StackOverflowException here too! 

I understand that Unity is trying to protect me from using partially initialized objects, but I want this protection to be an option, not an obligation.

Question: Is current behavior prohibited?

+6
dependency-injection unity-container circular-dependency
source share
3 answers

I think you cannot use circular dependencies with unity at all.

See: http://msdn.microsoft.com/en-us/library/cc440934.aspx

+5
source share

One way: use lazy loading for dependencies of one of the classes:

 [TestFixture] public class CircularUnityTest { IUnityContainer container; [SetUp] public void SetUp() { container = new UnityContainer(); container.RegisterType(typeof(ILazy<>), typeof(Lazy<>)); container.RegisterType<FirstClass>(new ContainerControlledLifetimeManager()); container.RegisterType<SecondClass>(new ContainerControlledLifetimeManager()); } [Test] public void CanResolveFirstClass() { var first = container.Resolve<FirstClass>(); Assert.IsNotNull(first); } [Test] public void CanResolveSecondClass() { var second = container.Resolve<SecondClass>(); Assert.IsNotNull(second); } [Test] public void CanGetFirstFromSecond() { var second = container.Resolve<SecondClass>(); Assert.IsNotNull(second.First); } } class FirstClass { [Dependency] public SecondClass Second { get; set; } } class SecondClass { private readonly ILazy<FirstClass> lazyFirst; public FirstClass First { get { return lazyFirst.Resolve(); } } public SecondClass(ILazy<FirstClass> lazyFirst) { this.lazyFirst = lazyFirst; } } public interface ILazy<T> { T Resolve(); } public class Lazy<T> : ILazy<T> { IUnityContainer container; public Lazy(IUnityContainer container) { this.container = container; } public T Resolve() { return container.Resolve<T>(); } } 
+2
source share

you can use RegisterInstance instead of RegisterType to achieve your goal. It will behave just like a singleton - it will use the same instance every time Resolve is called. Take a look at this example:

 class FirstClass { [Dependency] public SecondClass Second { get; set; } } class SecondClass { public readonly FirstClass First; public SecondClass(FirstClass first) { First = first; } } class Program { static void Main(string[] args) { IUnityContainer container = new UnityContainer(); var firstObj = new FirstClass(); var secondObj = new SecondClass(firstObj); firstObj.Second = secondObj; // Register instance instead of type!!! container.RegisterInstance<FirstClass>(firstObj); container.RegisterType<SecondClass>(); var first = container.Resolve<FirstClass>(); var second = container.Resolve<SecondClass>(); } } 

Greetings

Pavel

+1
source share

All Articles