I've got the simplest kind of circular dependency in structuremap - class A relies on class B in its constructor, and class B relies on class A in its constructor. To break the dependency, I made class B take class A as a property, rather than a constructor argument, but structuremap still complains.
I've seen circular dependencies broken using this method in other DI frameworks - is this a problem with Structuremap or am I doing something wrong?
Edit: I should mention that class B's property is an array of class A instances, wired up like this:
x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault();
Just to clarify, I want the following sequence of events to occur:
And I want all this to happen using autowiring, if possible...
Edit 2: Here's a simplified example that uses explicit wiring up:
interface ILoader { }
interface ILoaderManager { }
class Loader : ILoader
{
public Loader(ILoaderManager lm) { }
}
class LoaderManager : ILoaderManager
{
public ILoader Loader { get; set; } // Was an array, but same circular dependency appears here
}
ObjectFactory.Configure
(
x =>
{
x.For<ILoader>.Singleton().Use<Loader>();
x.For<ILoaderManager>().Singleton().Use<LoaderManager>().OnCreation((c, a) => a.Loader = c.GetInstance<ILoader>());
}
);
Validating the configuration causes "Bidirectional Dependency Problem detected with RequestedType: IocTest2.ILoader..."
But circular dependencies in software are solvable because the dependencies are always self-imposed by the developers. To break the circle, all you have to do is break one of the links. One option might simply be to come up with another way to produce one of the dependencies, in order to bootstrap the process.
A simple way to break the cycle is by telling Spring to initialize one of the beans lazily. So, instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it's first needed.
If you are predominantly using constructor injections then it is possible to create circular dependencies in Spring.
There are a couple of options to get rid of circular dependencies. For a longer chain, A -> B -> C -> D -> A , if one of the references is removed (for instance, the D -> A reference), the cyclic reference pattern is broken, as well. For simpler patterns, such as A -> B -> A , refactoring may be necessary.
StructureMap can handle bi-directional situation also with a workaround using Lazy resolution.
If you have a simple situation like ClassA
that depends on ClassB
and ClassB
that depends of ClassA
, then you can choose one of them and convert the dependency as a Lazy dependency. This way worked for me and that error never appeared again..
public class ClassA
{
private readonly Lazy<IClassB> _classB;
public ClassA(Lazy<IClassB> classB)
{
_classB = classB;
}
public IClassB ClassB => _classB.Value;
}
public class ClassB
{
public IClassA _classA { get; set; }
public ClassB (IClassA classA)
{
_classA = classA;
}
}
More info here: http://structuremap.github.io/the-container/lazy-resolution/
The closest you can get is something like this:
x.For<IB>().Use<B>()
.OnCreation((ctx, instance) =>
{
instance.ArrayOfA = new IA[] {new A(instance) };
});
If A
has other dependencies that you want to resolve from the container, you can retrieve them from ctx
within the OnCreation lambda.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With