Circular dependencies between services

Topics: Web Client Software Factory
Mar 25, 2008 at 10:50 AM
Hi, All! I would like to know your opinion about such question. Consider, there is a class ServiceA, which implements IServiceA and class ServiceB, which implements IServiceB. Both this services can be registered in Services collection with AddNew. Consider now, implementation of ServiceA requires calling methods of IServiceB. In this case I add a property public IServiceB to class ServiceA and mark it with ServiceDependency. But, if implementation of class ServiceB requires calling IServiceA, and I put property public IServiceA to this class, I lost the opportunity to register any of this services, because it leads to circular dependency and ObjectBuilder crashes while building this instances. This time I use a workaround: I've created property public CompositionContainer container, marked with Dependency attribute in both ServiceA and ServiceB classes and property ServiceB in class ServiceA (and similar property ServiceA in class ServiceB) implemented as:

private IServiceB ServiceB
{
get { return container.Services.Get<IServiceB>(); }
}

Is there more elegant way to solve this problem? Though my solution works, there are difficulties in unit testing. As I saw in reference implementations, people are creating instances of such services manually and also manually inject dependant objects to them (instead of ObjectBuilder) when building instances for testing. An example from OrderManagementRI:

private TestableOrdersController GetOrderControllerInitialized()
{
TestableOrdersController controller = new TestableOrdersController(
new MockHttpContextLocatorService(),
new MockOrderEntryFlowService()
);
controller.InitializeState(new StateValue<Order>());
return controller;
}

In my unit tests I inject into the CompositionContainer property, which will be used inside class to find such interdependent services. Of course, in unit test I have no real CompositionContainer and forced to create it manually. As to me, it's a bit extraordinary scenario, I have never seen analogues in samples.
Mar 25, 2008 at 1:41 PM
Edited Mar 25, 2008 at 1:41 PM


YMarkov wrote:
Consider, there is a class ServiceA, which implements IServiceA and class ServiceB, which implements IServiceB. Both this services can be registered in Services collection with AddNew. Consider now, implementation of ServiceA requires calling methods of IServiceB. In this case I add a property public IServiceB to class ServiceA and mark it with ServiceDependency. But, if implementation of class ServiceB requires calling IServiceA, and I put property public IServiceA to this class, I lost the opportunity to register any of this services, because it leads to circular dependency and ObjectBuilder crashes while building this instances.

Would a Facade be a practical solution?

BTW, if you use two squiggley bracketts around your code , e.g., {{ ..... }} your code will remain intact, e.g.
        private TestableOrdersController GetOrderControllerInitialized()
        {
            TestableOrdersController controller = new TestableOrdersController(
                new MockHttpContextLocatorService(),
                new MockOrderEntryFlowService()
            );
            controller.InitializeState(new StateValue<Order>());
            return controller;
        }

Mar 25, 2008 at 2:17 PM
Do you mean to build a facade on the top of ServiceA and ServiceB, i.e. it will include the fuctionality of both of them? Ok, I'll evaluate this decision.
Thanks for formatting advice. I've tried to use single brackets {..}, as it described in "Markup Guide", and it didn't give any effect, but double brackets really does :-)
Mar 27, 2008 at 7:06 PM
You might want to move the interfaces to thier own assemblies.
This was, ServiceA's implementation can reference the assembly with IServiceA (IServiceAInterfaces.DLL or something better named), and the assembly with IServiceB (IServiceAInterfaces.DLL or whatever). ServiceB's implementation would reference those two assemblies as well, but there is no circular reference.

Michael Puleio - patterns & practices
Webhttp://msdn.microsoft.com/practices/
Bloghttp://blogs.msdn.com/mpuleio/
Mar 27, 2008 at 10:00 PM


MichaelPuleio wrote:
You might want to move the interfaces to thier own assemblies.
This was, ServiceA's implementation can reference the assembly with IServiceA (IServiceAInterfaces.DLL or something better named), and the assembly with IServiceB (IServiceAInterfaces.DLL or whatever). ServiceB's implementation would reference those two assemblies as well, but there is no circular reference.


This is not a my case :-). The problem is not to solve circular dependency between assemblies, because both services are logically coupled with each other and sit in one assembly. Let me show a short snippet:

public interface IServiceA
{
	int Foo();
}
 
public interface IServiceB
{
	int Bar();
}
 
public class ServiceA : IServiceA
{
	private IServiceB serviceB;
	
	[ServiceDependency]
	public IServiceB ServiceB
	{
		set { serviceB = value; }
	}
	
	public int Foo()
	{
		int x = serviceB.Bar();
		return x + 1;
	}
}
 
public class ServiceB : IServiceB
{
	private IServiceA serviceA;
	
	[ServiceDependency]
	public IServiceA ServiceA
	{
		set { serviceA = value; }
	}
 
	public int Bar()
	{
		int y = serviceA.Foo();
		return y - 2;
	}
}
 
	// Trying to register this services... An exception already in first line!
	protected virtual void AddGlobalServices(IServiceCollection globalServices)
	{
		globalServices.AddNew<ServiceA, IServiceA>(); // Stack overflow!
		globalServices.AddNew<ServiceB, IServiceB>();
	}

Such a snippet is compiled wonderfully. But, obviously, an ObjectBuilder will fail while registering any of this services, because of an interdependent declaration. To solve it, I use a "lazy initialization" approach by means of container.Services.Get(), as described in the first post. Does this approach have a right for existance? :-)
Mar 27, 2008 at 10:50 PM
Looks like a chicken and egg problem to me.

I remember reading a section in the Unity http://www.codeplex.com/unity regarding avoiding circular references. I know WCSF does not use Unity but might be useful read.



YMarkov wrote:

This is not a my case :-). The problem is not to solve circular dependency between assemblies, because both services are logically coupled with each other and sit in one assembly. Let me show a short snippet:

Such a snippet is compiled wonderfully. But, obviously, an ObjectBuilder will fail while registering any of this services, because of an interdependent declaration. To solve it, I use a "lazy initialization" approach by means of container.Services.Get(), as described in the first post. Does this approach have a right for existance? :-)