ASP.NET Core DI в библиотеке классов? - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть проект ASP.NET Core 2.1, который ссылается на проект «Уровень доступа к данным» типа .NET Core Class Library.

Для доступа к данным требуется строка подключения из appsettings.json в ASPПроект .NET Core.

Я создал простой контейнер, подобный этому:

public class DatabaseConnectionString : IDatabaseConnectionString
{
    private readonly string _connectionString;

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

    public string ConnectionString {
        get { return _connectionString; }
        set {  }
    }
}

В ASP.NET Core Startup.cs> ConfigureService у меня есть это:

services.AddScoped<IDatabaseConnectionString>(p => new DatabaseConnectionString(Configuration.GetConnectionString("DefaultConnection")));

Я знаю, что могу добавить IDatabaseConnectionString в конструктор контроллера в ASP.NET, чтобы получить контейнер.Но как я могу получить это, находясь в библиотеке классов?Я не хочу передавать его полностью из контроллера, и просто добавление IDatabaseConnectionString в конструктор класса в библиотеке классов не работает.

Мне, вероятно, нужен сервис, где я могу попросить создатьобъект класса, и пусть служба заполняет интерфейс конструктора правильными объектами?

Например, заполнение строки IDatabasConnectionString в этом классе:

public class UserFactory : FactoryBase
{
    private readonly IDatabaseConnectionString _iDatabaseConnectionString;

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

}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Я знаю, что могу добавить 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;
    }
}

Кстати, как сказал @YeldarKurmangaliyev, ваша DatabaseConnectionStringдолжно быть так, если вы хотите сделать его доступным только для чтения:

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

    public DatabaseConnectionString(string connectionString)
    {
        ConnectionString = connectionString;
    }
}
0 голосов
/ 20 февраля 2019

Нет никакой разницы между контроллером и классом из библиотеки классов.Вам необходимо

  1. Определить класс в библиотеке классов и вставить в нее IDatabaseConnectionString.Ваш UserFactory - правильный путь.

  2. зарегистрируйте UserFactory для DI

    serviceCollection.AddScoped<IUserFactory, UserFactory>();
    
  3. Разрешите UserFactory с помощью DI.Например, используйте UserFactory в качестве параметра конструктора в некотором контроллере.Все соединяется DI автоматически.

    public MyController(IUserFactory userFactory)
    {
        _userFactory = myUserFactory;
    }
    

Здесь - хорошее объяснение для понимания Корень композиции .

...