首页 > 解决方案 > 使用 DI 模拟调用 .Net Core 类库

问题描述

我无法创建一个控制台程序来调用引用类库中的注册方法。除了配置之外,我无法注入依赖项。

类库包含要调用的代码:

public interface IMyClient
{
    Task DoSomething(Request request);
}

public class MyClient : IMyClient
{
    private readonly MyClientConfig _config;
    private readonly ILogger<MClient> _logger;
    private readonly HttpClient _client;

    public MyClient()
    {

    }

    public MyClient(MyClientConfig config, ILogger<MyClient> logger, HttpClient client)
    {
        _config = config;
        _logger = logger;
        _client = client;
    }

    public async Task DoSomething(Request request)
    {
        // BREAKPOINT HERE HAS config (id = 1) but logger & client are null
    }
}

和控制台程序

class Program
{
    private static IServiceProvider _serviceProvider;
    static void Main(string[] args)
    {
        RegisterServices();
        IServiceScope scope = _serviceProvider.CreateScope();

        var request = new Request()
        {
            Id = 1
        };

        scope.ServiceProvider.GetRequiredService<IMyClient>().DoSomething(request);

        DisposeServices();
    }

    private static void RegisterServices()
    {
        var myClientConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .Build().GetSection("MyClient").Get<MyClientConfig>();


        var services = new ServiceCollection();
        services.AddSingleton<IMyClient, MyClient>();
        services.AddSingleton<IMyClientConfig>(myClientConfig);
        _serviceProvider = services.BuildServiceProvider(true);
    }

    private static void DisposeServices()
    {
        if (_serviceProvider == null)
        {
            return;
        }
        if (_serviceProvider is IDisposable)
        {
            ((IDisposable)_serviceProvider).Dispose();
        }
    }
}

我尝试添加

services.AddSingleton<HttpClient>(new HttpClient());

获取 HttpCLient 注入但无济于事。

任何有关在引用项目中测试对 DoSomething 的调用的帮助或建议

标签: c#.net-coredependency-injection

解决方案


您没有配置您的LoggerHttpClientservices. 您还可能缺少一个额外的 Nuget 包,Microsoft.Extensions.Logging.Console如果缺少,请安装它,因为您提到这是一个控制台应用程序

修改您的代码如下:

    private static void RegisterServices()
    {

        var myClientConfig = new ConfigurationBuilder()
                                .AddJsonFile("appsettings.json", true, true)
                                .Build().GetSection("MyClient").Get<MyClientConfig>();

        var services = new ServiceCollection();
        services.AddSingleton<IMyClient, MyClient>();

        // Configure logging service
        services.AddLogging(cfg => cfg.AddConsole())
                .AddTransient<MyClient>();

        // Configure HttpClient - might need some constructor params, depending on your use case
        services.AddSingleton<HttpClient>(new HttpClient());

        _serviceProvider = services.BuildServiceProvider(true);
    }

另外,非常重要:删除你的空构造函数MyClient!你永远不想要那一击!事实上,让程序在调试中崩溃比点击构造函数要好得多,因为它会产生工作的外观——就像你现在所处的情况一样。

添加代码时您的代码“没有做任何不同”的原因services.AddSingleton<HttpClient>(new HttpClient());因为您的构造函数为空- 因为Logger服务仍未配置,DI 框架无法匹配正确的构造函数 - 所以不是得到一个有意义的错误,空的构造函数运行(因为它总是匹配) - 导致调试痛苦和痛苦

顺便说一句,我建议阅读 DI 如何在下面工作(甚至可以构建自己的 DI 容器,一个非常简单的容器,用于练习。不要在生产中使用自己的 DI 容器!)。这是一篇好文章,作者实际上是发明了这些东西:https ://martinfowler.com/articles/injection.html


推荐阅读