Reputation: 5323
I am using unity in a Winforms app by injecting the dependency into the constructor of the form (I know this is not best practice) but it does work but I am getting a stackoverflowexception when I am trying to load the mdi form.
is there any way to trace what unity is trying to resolve and somehow find out what is happening?
I have a working example that I know works using this 'design'.
I know this is not an ideal design and I plan on introducing a Presenter down the line but for now this should work and I don't know why it is not
EDIT: I know I have services that reference each other for example
public class Service1(IService2, IService3, IService4):IService1
public class Service2(IService1, IService5):IService2
will this cause an exception?
EDIT2: yes I just created an quick app with this circular reference as listed in my first edit and I got a StackOverflowException - obviously not allowed.
Upvotes: 3
Views: 3967
Reputation: 2151
When you catch the exception in VS go inside it and follow InnerException
. Unity should print all registered types and you can see which is missing.
Also look at stack trace. Usually StackOverflow
appears when you have circular dependecies like this:
class A { A(B b) { ... } }
class B { B(A a) { ... } }
A
depends on B
and vice versa. Unity will try to inject in ctor
of A
a B
instance but a B
instance needs an A
instance which, again, needs a B
and so on.
This example is a trivial one but in real work the circularity is harder to spot as there might be a more complex graph of dependencies, between different libraries, like A
-> B
-> C
-> D
-> A
(where "->" means "depends on").
EDIT
Yes, that cross-references services can lead you to a stackoverflow exception if at the moment you're resolving IService1
, IService1
itself is not registered yet;
Solution 1 You can bypass this problem if types registration and resolving happens in two steps (rough idea):
Registration register both IService1
and its type and IService2
and its type. This step is doing only registration code and do not process any other things (UI, startup logic, unity resolving, http comms, etc).
Actual application logic starts; now you can resolve anything.
Solution 2
Use empty ctors
and doing the resolve inside Service
class. You can use RegisterType
method to specify that the empty ctor
must be called:
container.RegisterType<IServiceProvider, ServiceContainer>(new InjectionConstructor());
Here are more details about circular references with dependency injection using Unity.
Solution 3
Use Lazy<IService>
for resolving. Using this the actual resolving will happen on demand, more specific when the first time Lazy.Value
property is called first time.
Upvotes: 7