用DI模拟调用.Net Core类库

问题描述

我在创建控制台程序以调用引用的类库中的enroll方法时遇到麻烦。除了配置,我无法注入依赖项。

Class库包含要调用的代码:

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的调用的任何帮助或建议

解决方法

您没有在Logger中配置HttpClientservices。您还可能会缺少一个额外的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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...