【问题标题】:how to inject depencies to constructor controller如何将依赖项注入构造函数控制器
【发布时间】:2021-09-08 17:01:53
【问题描述】:

我正在尝试配置一个 API,控制器使用依赖注入将对象注入此控制器

public class BaseAPIController
{
    private readonly Repository _repository;
    public BaseAPIController(Repository repository)
    {
        _repository = repository;
    }

    // some common functions and properties are declared here
}
public class AccountController : BaseAPIController
{
    public AccountController(Repository repository) : base(repository)
    {  }
}

但它会抛出一个异常,告诉“无法构建某些服务......”

我尝试了一个使用 ILogger<Repository> 而不是使用 Repository 实例的解决方案,然后它可以正常运行

public class AccountController : BaseAPIController
{
    public AccountController(ILogger<Repository> repository) : base(repository)
    {  }
}

startup.cs代码中的注册服务

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddScoped<IRepository, Repository>();
    services.AddSingleton<WeatherForecastController, WeatherForecastController>();
}

以及Repository类的声明

public interface IRepository
{
    void DoSomething1();
    void DoSomething2();
    void DoSomething3();        
}
public class Repository : IRepository
{
    public readonly string _connectionString;

    public Repository(string connectionString)
    {
        _connectionString = connectionString;
    }
    public void DoSomething1() {}
    public void DoSomething2() {}
    public void DoSomething3() {}
}

如何在不使用 ILogger 实例的情况下存档上述配置 谢谢

【问题讨论】:

  • BaseAPIController 类是什么样的?除非服务需要,否则您不必使用 ILogger。
  • 啊对不起,我错过了BaseAPIController的继承。我在 post it 容器中编辑了一些可以在所有控制器中使用的通用函数和属性的声明
  • 仍有一些类无法诊断。请包括所有相关代码,例如存储库。此外,请包括您在哪里注册服务,例如在您的 Startup.cs 文件中。如果它未能构建依赖项,则可能是您没有注册依赖服务,或者它的范围是错误的,例如单例服务将要求其依赖的服务也是单例。
  • 我刚刚编辑了上面的代码,这只是我基于 Visual Studio 的 ASP.net core API 模板新建的项目
  • 问题是 Repository 类没有无参数构造函数,因此 DI 无法创建它的实例。理想情况下,您应该使用 IOptions 而不是字符串来传递连接字符串。

标签: api asp.net-core dependency-injection singleton


【解决方案1】:

这是您进行的注册:

services.AddScoped<IRepository, Repository>();

但这是AccountController的构造函数:

AccountController(Repository repository)

注意AccountController 如何取决于具体类型Repository;不在IRepository 界面上。由于此注册,Repository 只能通过其IRepository 接口解析,但不能直接解析(这是 MS.DI 的设计)。

因此,解决方案是将AccountController 的构造函数更改为以下内容:

AccountController(IRepository repository)

【讨论】:

  • 那么我如何在测试方法中初始化Repository 对象的实例以实现一些它。我的意思是在测试方法中,我必须像这样创建控制器实例:var controller = new AccountController(.....); //where .... is an instance of Repository object with fake connection string in it。谢谢
  • 嗨,明,在测试中,您通常会注入一个假版本。您可以通过创建一个实现IRepositoryFakeRepository 类来做到这一点,您可以将其提供给控制器,如下所示:new AccountController(new FakeRepository())
  • 如果你愿意,你也可以在你的测试中注入真实的仓库,如下:new AxcountController(new Repository(..)).
【解决方案2】:

问题在于 DI 无法创建 Repository 的实例,因为没有无参数构造函数。 Take a look 在文档中用于注入设置而不是在构造函数中需要字符串。将连接字符串添加到 appsettings.json 文件中:

{
  "AppSettings": {
    "ConnectionString": "<connection_string>"        
  }
}

ConfigureServices注册你的设置类:

public class AppSettings
{
    public string ConnectionString;
}

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration.GetSection(AppSettings));
    ...
}

那么您的 Repository 类构造函数将如下所示:

public Repository(IOptions<PositionOptions> options)
{
    _connectionString = options.Value.ConnectionString;
}

您还需要将接口IRepository,而不是具体的类注入到您的控制器中。

public class BaseAPIController
{
    private readonly IRepository _repository;
    public BaseAPIController(IRepository repository)
    {
        _repository = repository;
    }

    // some common functions and properties are declared here
}

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 2011-02-02
    相关资源
    最近更新 更多