3

Currently we experience a circular dependency in castle windor (or probably any ioc container). We have:

public class MessageHandler : IMessageHandler
{
    private readonly IService service;

    public MessageHandler(IService service)
    {
        this.service = service;
    }

    private void OnIncommingMessage(string message)
    {
        service.DoWork(message);
    }

    public void SendMessage(string message)
    {
        //sendMessage code
    }
}

public class Service : IService
{
    private readonly IMessageHandler messageHandler;

    public Service(IMessageHandler messageHandler)
    {
        this.messageHandler = messageHandler;
    }

    public void DoWork(string work)
    {
        //Do Work
    }

    private void SomeMethodNeedsToPushData(string message)
    {
        messageHandler.SendMessage(message);
    }

}

public interface IService
{
    void DoWork(string work);
}

public interface IMessageHandler
{
    void SendMessage(string message);
}

Is there a clean way to solve above problem in Castle windsor? I dont like to go via property injection because both classes depend on the other so in my opinion this should always go via constructor injection.

Patrick
  • 2,730
  • 4
  • 33
  • 55
  • 6
    Rhetorical Question: If you weren't using an IoC container, how would you solve the problem? – Roger Lipscombe Jul 29 '15 at 07:14
  • 1
    The problem lies in your design. Do not try to break the cycle by moving to property injection, because the dependency cycle will still exist. A common solution is to introduce a new class that both IMessageHandler and IService can both depend on. – Steven Jul 29 '15 at 09:29
  • 1
    see answer [here](http://stackoverflow.com/questions/22488846/circular-reference-using-ioc/22491684#22491684) - register `Func` instead of `YourType`. PS: Remove duplicate question – Ilya Palkin Jul 30 '15 at 08:00

1 Answers1

2

I believe the problem is in the design of your classes. Think you can workaround the circular dependency by introducing observable pattern.

public interface IService : IDisposable
{
    void Serve(string message);
}

public interface IMessageHandler : IService
{
}

public class MessageHandler : IMessageHandler
{
    private readonly IWorkDispatcher workDispatcher;

    public MessageHandler (IServicesRegistry servicesRegistry)
    {
        servicesRegistry.RegisterService(WorkType.MessageHandler, this);
        this.servicesRegistry = servicesRegistry;
    }
    private void OnIncommingMessage(string message)
    {
        servicesRegistry.SendMessage(WorkType.Service, message);
    }

    public void Serve(string message) // was SendMessage(string message)
    {
        //sendMessage code
    }

    public void Dispose()
    {
        servicesRegistry.RemoveService(this);
    }
}

public interface IWorkerService : IService
{
}

public class WorkerService: IWorkerService 
{
    private readonly IServicesRegistry servicesRegistry

    public Service(IServicesRegistry servicesRegistry)
    {
        servicesRegistry.RegisterService(WorkType.Worker, this);
        this.servicesRegistry = servicesRegistry;
    }

    public void Serve(string message); // was DoWork(string work)
    {
        //Do Work
    }

    private void SomeMethodNeedsToPushData(string message)
    {
        servicesRegistry.SendMessage(WorkType.MessageHandler, message);
    }

    public void Dispose()
    {
        servicesRegistry.RemoveService(this);
    }
}

public enum WorkType
{
    Service,
    MessageHandler
}

public interface IServicesRegistry
{
    void RegisterService(WorkType workType, IService service);
    void RemoveService(IService service);
    void QueueWork(WorkType workType, string message);
}