简体   繁体   English

使用依赖注入解决循环依赖关系

[英]Resolve circular dependency with Dependency Injection

I have three classes which implement their interface. 我有三个实现其接口的类。

Orders 命令

public interface IOrderService
{
   //SomeOrderFunction()
}

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

Drivers 驱动程序

public interface IDriverService
{
   //SomeDriverFunction()
}

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

Plans -- Uses Driver and Plan services 计划 - 使用驱动程序和计划服务

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();
}

The issue I now have though is that the Order and Driver service need to talk back to the plan service when either an Order or Driver gets changed, how would I go about doing this without having a circular dependency? 我现在遇到的问题是订单和驱动程序服务需要在订单或驱动程序更改时与计划服务进行对话,如何在没有循环依赖的情况下执行此操作?

Edit : Specifically I've been looking at creating a fourth service that manages all the other ones such as the one explained in this article. 编辑 :具体来说,我一直在寻找创建第四个管理所有其他服务的服务,例如本文中解释的服务。

Breaking Dependency Cycles 打破依赖循环

What confuses me about this implementation is my Plan class, does my plan class implement both the new class AND the IPlan interface? 让我对这个实现感到困惑的是我的Plan类,我的计划类是否同时实现了新类和IPlan接口?

via events. 通过活动。

create an event handler interface: 创建事件处理程序接口:

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

then define an event: 然后定义一个事件:

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

Now let one of the other classes implement it: 现在让其他类之一实现它:

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

now, to be able to publish events you need another interface: 现在,为了能够发布您需要另一个界面的事件:

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

Which can be invoked from your class: 哪个可以从你的班级调用:

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 } );
}

.. to invoke it we can use service location (implementation detail): ..要调用它我们可以使用服务位置(实现细节):

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);
            }
        }

    }
}

.. as a result you get low coupling between the classes. ..结果你得到了类之间的低耦合。

First, rethink your approach. 首先,重新考虑你的方法。

Second, if you still insist on having a circular dependency, you could make it less explicit by making the dependent service responsible for setting the backward dependency, eg 其次,如果你仍然坚持循环依赖,你可以通过让依赖服务负责设置后向依赖来减少它,例如

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

....

public class PlanService: IPlanService
{
   private readonly IOrderService _orderService;

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

Inject a Func<IPlanService> instead of the IPlanService into the IOrderService and IDriverService . 将一个Func<IPlanService>而不是IPlanService注入IOrderServiceIDriverService This 'breaks' the chain of instances that the container has to create. 这会“打破”容器必须创建的实例链。

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

    private readonly Func<IPlanService> _planServiceFactory;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM