Search code examples
c#asp.net-coredependency-injection

(Interface) A circular dependency was detected for the service of type


I have 2 interfaces:

public interface IPedidoService
{
    UsuarioDrogueria CUsuarioDrogueria(string userId, int idDrogueria);
    List<PedidoComboProducto> CPedidosCombosProductos(int idcombo, int idPedido);  
} 

public interface IEmailService
{
    void SendEmailAttachment(string email, string subject, string archive);
    void SendNotificationEmail(List<Pedido> pedidos, string email, Drogueria drog);
    void SendNotificationEmailADM(Pedido pedido) ;
}

I want to use the functions from IEmailService inside IPedidoService, so I inject it in its constructor when I create the respository.

public class PedidoService : IPedidoService
{
    private readonly IEmailService emailService;

    public PedidoService(IEmailService e)
    {
        this.emailService = e;
    }
}

Up until here everything works fine, but when I try to do reverse the roles (IPedidoService functions inside IEmailService):

public class EmailService : IEmailService
{
    private readonly IPedidoService pedidoSettings;

    public EmailService(IPedidoService p)
    {
        this.pedidoSettings = p;
    }
}

I end up getting this exception:

System.InvalidOperationException: A circular dependency was detected for the service of type
   'EnvioPedidos.Data.Abstract.IPedidoService'.
    EnvioPedidos.Data.Abstract.IPedidoService(EnvioPedidos.PedidoService) ->
    EnvioPedidos.Data.Abstract.IEmailService(EnvioPedidos.EmailService) ->
    EnvioPedidos.Data.Abstract.IPedidoService

Can anybody help me trace the issue here?


Solution

  • A simple way is to use Lazy<T> class which is based on this blog:

    Custom extension method:

    public static class LazyResolutionMiddlewareExtensions
    {
        public static IServiceCollection AddLazyResolution(this IServiceCollection services)
        {
            return services.AddTransient(
                typeof(Lazy<>),
                typeof(LazilyResolved<>));
        }
    }
    
    public class LazilyResolved<T> : Lazy<T>
    {
        public LazilyResolved(IServiceProvider serviceProvider)
            : base(serviceProvider.GetRequiredService<T>)
        {
        }
    }
    

    Configure in Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {           
        //services.AddSingleton<IPedidoService, PedidoService>();
        //services.AddSingleton<IEmailService, EmailService>();
    
        services.AddLazyResolution();
    }
    

    Change your implements class:

    public class PedidoService : IPedidoService
    {
        private readonly Lazy<IEmailService> emailService;
    
        public PedidoService(Lazy<IEmailService> e)
        {
            this.emailService = e;
        }
    
        //...
    }
    public class EmailService : IEmailService
    {
        private readonly Lazy<IPedidoService> pedidoSettings;
    
        public EmailService(Lazy<IPedidoService> p)
        {
            this.pedidoSettings = p;
        }
        //...
    }