类库中的 ASP.NET Core DI?

Ban*_*hee 7 c# dependency-injection asp.net-core

我有一个 ASP.NET Core 2.1 项目,它引用了一个典型的 .NET Core 类库的“数据访问层”项目。

数据访问层需要来自 ASP.NET Core 项目中 appsettings.json 的连接字符串。

我创建了一个像这样的简单容器:

public class DatabaseConnectionString : IDatabaseConnectionString
{
    private readonly string _connectionString;

    public DatabaseConnectionString(string connectionString)
    {
        _connectionString = connectionString;
    }

    public string ConnectionString {
        get { return _connectionString; }
        set {  }
    }
}
Run Code Online (Sandbox Code Playgroud)

在 ASP.NET Core Startup.cs > ConfigureService 我有这个:

services.AddScoped<IDatabaseConnectionString>(p => new DatabaseConnectionString(Configuration.GetConnectionString("DefaultConnection")));
Run Code Online (Sandbox Code Playgroud)

我知道我可以将 IDatabaseConnectionString 添加到 ASP.NET 中控制器的构造函数以获取容器。但是如何在类库中获取它?我不想从控制器一直向下传递它,只是将 IDatabaseConnectionString 添加到类库中类的构造函数是行不通的。

我可能需要一个服务,我可以要求创建一个类的对象并让该服务使用正确的对象填充构造函数接口?

例如填写此类中的 IDatabasConnectionString :

public class UserFactory : FactoryBase
{
    private readonly IDatabaseConnectionString _iDatabaseConnectionString;

    public UserFactory(IDatabaseConnectionString connectionString)
    {
        _iDatabaseConnectionString = connectionString;
    }

}
Run Code Online (Sandbox Code Playgroud)

Kar*_*ral 5

类库中的控制器和类之间没有区别。你需要

  1. 在类库中定义一个类并注入IDatabaseConnectionString其中。你的方法UserFactory是正确的。

  2. 注册UserFactoryDI

    serviceCollection.AddScoped<IUserFactory, UserFactory>();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 通过 DI 解析 UserFactory。例如,在某些控制器中使用 UserFactory 作为构造函数参数。一切都由 DI 自动连接。

    public MyController(IUserFactory userFactory)
    {
        _userFactory = myUserFactory;
    }
    
    Run Code Online (Sandbox Code Playgroud)

是理解Composition root的好解释。


SO *_*ood 5

我知道我可以将 IDatabaseConnectionString 添加到 ASP.NET 中控制器的构造函数以获取容器。

不,那不是必需的,那是错误的。

仅将 IDatabaseConnectionString 添加到类库中类的构造函数是行不通的。

这是行不通的,因为你需要创建将使用连接字符串的服务,并把它添加到服务容器。

例如:

public class Repository: IRepository
{
    public Repository(IDatabaseConnectionString databaseConnectionString)
    {
        _databaseConnectionString = databaseConnectionString;
    }
}

public class ServiceThatRequiresDatabase : IServiceThatRequiresDatabase
{
    public ServiceThatRequiresDatabase(IRepository repository)
    {
        _repository = repository;
    }
}

// ...
services.AddScoped<IRepository, Repository>();
services.AddScoped<IServiceThatRequiresDatabase, ServiceThatRequiresDatabase>();


public class HomeController : Controller
{
    public HomeController(IServiceThatRequiresDatabase service)
    {
        _service = service;
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,正如@YeldarKurmangaliyev 所说,如果您想将其设为只读,您的 DatabaseConnectionString 应该是这样的:

public class DatabaseConnectionString : IDatabaseConnectionString
{
    public string ConnectionString { get; }

    public DatabaseConnectionString(string connectionString)
    {
        ConnectionString = connectionString;
    }
}
Run Code Online (Sandbox Code Playgroud)