Reputation: 3696
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..."
Upvotes: 9
Views: 11101
Reputation: 2169
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/
Upvotes: 6
Reputation: 8557
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.
Upvotes: 3
Reputation: 5190
StructureMap is likely performing Setter Injection where it will populate public settable properties on an object it's resolving. According to the documentation,
By default, all public "Setters" are optional, meaning that these setters will only be set if they are explicitly configured for a specific Instance
So have you by chance set up the properties to be auto wired? If so, you'll still have the circular dependency issue.
Edit: I see that you have. In your instance because B has A[] injected, StructureMap must resolve each A's dependency for a B that needs A[], and so on...
Upvotes: 1