【问题标题】:circular dependency in dotnet core 2.0 console application using ServiceCollectiondotnet core 2.0 控制台应用程序中使用 ServiceCollection 的循环依赖
【发布时间】:2017-11-04 23:30:01
【问题描述】:

我正在尝试使用 Dotnet 核心 2.0 Microsoft.Extensions.DependencyInjection nuget 包附带的 IServiceCollection 设置一个简单的依赖项注入。我是新手,所以我从一个小实验开始:

public interface IService
{
}

public class JobService : IService
{
    public IService m_service { get; set; }
    public JobService(IService service)
    {
        m_service = service;
    }
}

class Program
{
    static void Main(string[] args)
    {
        IServiceCollection serviceCollection = new ServiceCollection();
        ConfigureService(serviceCollection);
        var serviceProvider = serviceCollection.BuildServiceProvider();
        //exception on next line
        var service = serviceProvider.GetService<App>();
        Console.WriteLine("Hello World!");
    }

    private static void ConfigureService(IServiceCollection serviceCollection)
    {
        serviceCollection.AddTransient<IService, JobService>();
        serviceCollection.AddTransient<App>();
    }
}

以上内容应该向容器注册所有类型,但在运行时,我得到:

System.InvalidOperationException: '检测到'TestCore.IService' 类型的服务的循环依赖。'

我在我的实现中没有看到循环依赖。有人能指出这种循环依赖的来源吗?

至于服务,应该是注入到我做的这个App类中:

public class App
{
    private IService m_service;
    public App(IService service)
    {
        m_service = service;
    }
}

【问题讨论】:

    标签: c# .net-core


    【解决方案1】:

    由于循环依赖,依赖注入框架无法解析 IService 的依赖。 这是因为您对IService (JobService) 的实现本身依赖于IService 的实现(即它自己)。无法实例化 JobService,因为它依赖于自身。 DI 框架识别出这一点并抛出您所看到的异常。 为了避免这种情况,您需要使 JobService 依赖于不同接口的实现:

    public interface IService
    {
    }
    
    public interface IAnotherService
    {
    }
    
    public class JobService : IService
    {
        public IAnotherService m_service { get; set; }
        public JobService(IAnotherService service)
        {
            m_service = service;
        }
    }
    
    public class AnotherService : IAnotherService
    {
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            IServiceCollection serviceCollection = new ServiceCollection();
            ConfigureService(serviceCollection);
            var serviceProvider = serviceCollection.BuildServiceProvider();
            //exception on next line
            var service = serviceProvider.GetService<App>();
            Console.WriteLine("Hello World!");
        }
    
        private static void ConfigureService(IServiceCollection serviceCollection)
        {
            serviceCollection.AddTransient<IAnotherService, AnotherService>();
            serviceCollection.AddTransient<IService, JobService>();
            serviceCollection.AddTransient<App>();
        }
    }
    

    编辑/旁白:如果您使用 Autofac,您可以使用在 JobService 中保留 IService 依赖项,但使用 Named and Keyed Services 提供不同的实现。

    【讨论】:

    • 不,这不是问题所在。 IServiceJobService 的 OP 代码可以正常编译。
    • OP 遇到的不是编译错误。试试看,运行时会报错。
    • 你是说DI试图将JobService注入JobService的构造函数吗?
    • 是的(但由于这是一个无效的操作异常,我猜想尝试它太聪明了)。还有其他解释吗?
    • 感谢您的解释!据我了解,此错误消息也指向糟糕的设计。我刚刚用 Autofac 做了同样的例子,并且显示了相同的循环依赖消息(尽管 Autofac 实现了 Microsoft DI 包,所以不足为奇)。
    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多