2016-04-29 167 views
2

我有三个类实现它们的接口。用依赖注入解决循环依赖问题

订单

public interface IOrderService 
{ 
    //SomeOrderFunction() 
} 

public class OrderService: IOrderService 
{ 
    //SomeOrderFunction(); 
} 

驱动程序

public interface IDriverService 
{ 
    //SomeDriverFunction() 
} 

public class DriverService: IDriverService 
{ 
    //SomeDriverFunction(); 
} 

计划 - 使用驱动程序和计划服务

public interface IPlanService 
{ 
    //SomePlanFunction() 
} 

public class PlanService: IPlanService 
{ 
    private readonly IOrderService _orderService; 
    private readonly IDriverService _driverService; 

    public PlanService(IDriverService driverService, IOrderService orderService) 
    { 
     _orderService = orderService; 
     _driverService = driverService; 
    } 

    //PlanFunctionsThatUseServices(); 
} 

的问题,我现在虽然是订单和驱动程序服务需要当订单或驱动程序发生变化时,请回复计划服务,我该如何去做这件事没有循环依赖?

编辑: 具体来说,我一直在寻找创造,管理所有其他的人,如一个在这篇文章中解释第四服务。

Breaking Dependency Cycles

什么混淆了我这个实现我的计划类,不我的计划类实现两个新的类和接口IPLAN?

+2

我不认为没有这个参考是可能的。或者,您可以创建管理三种服务之间通信的_fourth_类。 – rbm

回答

1

首先,重新考虑你的方法。其次,如果你仍然坚持有一个循环依赖,你可以通过使依赖服务负责设置后向依赖关系来降低它的显式性,例如,

public interface IOrderService 
{ 
    //SomeOrderFunction() 
    IPlanService planService; 
} 

.... 

public class PlanService: IPlanService 
{ 
    private readonly IOrderService _orderService; 

    public PlanService(IOrderService orderService) 
    { 
     _orderService = orderService; 
     _orderService.planService = this; 
    } 
} 
+0

我试着考虑一种不同的方法,但最终需要告知计划订单或驱动程序已更改。 你对这种方法有什么看法,有一个知道所有服务的主节点。 http://blog.schauderhaft.de/2011/07/17/breaking-dependency-cylces/ –

+0

imho这是更多的解决方法,它也引入了时间耦合。 – jgauffin

6

via events。

创建一个事件处理接口:

public interface IEventSubscriber<TEvent> 
{ 
    void Handle(TEvent evt); 
} 

然后定义一个事件:

public class PlanCreated 
{ 
    public int PlanId { get; set; } 
    //and other properties. 
} 

现在让其他班的一个实现它:

public class DriverService : IDriverService, IEventSubscriber<PlanCreated> 
{ 
    public void Handle(PlanCreated evt) 
    { 
     //handle it here. 
    } 
} 

现在,是能够发布您需要另一个界面的活动:

public interface IEventPublisher 
{ 
    void Publish<TEvent>(TEvent evt); 
} 

可以从你的类中调用:

public class PlanService: IPlanService 
{ 
    private readonly IOrderService _orderService; 
    private readonly IDriverService _driverService; 

    public PlanService(IDriverService driverService, IOrderService orderService, IEventPublisher publisher) 
    { 
     _orderService = orderService; 
     _driverService = driverService; 
    } 

    public void PlanFunctionsThatUseServices() 
    { 

     //business code.... 


     _publisher.Publish(new PlanCreated(){ Id = plan.Id }); 
} 

..调用它,我们可以使用服务位置(实现细节):

public class EventPublisher : IEventPublisher 
{ 

    public EventPublisher(YourFavoriteContainer container) 
    { 
    } 


    public void Publish<TEvent>(TEvent evt) 
    { 
     using (var scope = _container.BeginLifetimeScope()) 
     { 
      var handlers = scope.ResolveAll<IEventSubscriber<TEvent>>(); 
      foreach (var handler in handlers) 
      { 
       //TODO: Handle exceptions= 
       handler.Handle(evt); 
      } 
     } 

    } 
} 

..因为你得到的结果类之间的低耦合。

+0

可以公平地指出,这种方法是一种众所周知的称为事件聚合器的模式。这使OP有机会自行找到更多信息。 –

+1

我不这么认为。事件聚合器将来自多个对象的事件通道***转换为单个对象***,以简化客户端的注册。该模式更多地处理相同对象类型的多个实例的事件。 – jgauffin

1

Func<IPlanService>而不是IPlanService注入IOrderServiceIDriverService。这'打破'容器必须创建的实例链。

public class OrderService { 
    public OrderService(Func<IPlanService> planServiceFactory) { 
     _planServiceFactory = planServiceFactory; 
    } 

    private readonly Func<IPlanService> _planServiceFactory; 

    public void SomeOrderFunction() { 
     _planServiceFactory().Notify(...); 
    } 
}