Я работаю над проектом ASP.NET Core 2.1, где мне нужно зарегистрироваться, а затем использовать одноэлементную службу внутри Startup.ConfigureServices.
У меня есть следующий код:
public void ConfigureServices(IServiceCollection services)
{
//....
//....
services.AddSingleton<IMyService,MyService>();
var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetService<IMyService>();
services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));
}
Приведенный выше код отлично работает, чтобы я мог использовать «MyService» внутри ConfigureServices. Однако позже в моем приложении, когда я пытаюсь использовать MyService, снова вызывается конструктор MyService. Почему он не использует уже созданный экземпляр, так как я зарегистрировал класс с помощью AddSingleton?
Обновлено: я решил отредактировать, чтобы добавить свою конечную цель, чтобы посмотреть, есть ли другой способ сделать это. Мой одноэлементный сервис предоставляет доступ к нескольким настройкам, которые могут быть получены из двух разных мест. Одним из таких параметров является строка подключения к БД. Мне нужна эта строка подключения в ConfigureServices, чтобы она была у меня, когда я вызываю services.AddDbContext. Я также хочу вести журнал в службе, которая получает параметры конфигурации, что означает, что мне также нужно получить ILoggerFactory.
в более ранних версиях вы могли просто вернуть поставщика, созданного вами из служб настройки, но я не уверен, что это было изменено в более поздних версиях ядра asp.net.
@Nkosi Я добавил правку в свой исходный пост, чтобы указать, что я пытаюсь сделать. Может быть, есть другой способ сделать это?
@Nkosi Я больше ничего не пробовал, так как даже не знаю, с чего начать.
Откуда ваша служба получает строку подключения?
Это может быть проблема XY.
@Nkosi служба получает строку подключения (и несколько других значений) либо из appSettings.json, если он есть, либо путем внешнего вызова API с использованием AWS SDK для извлечения из AWS Secrets Manager. Этот же сервис также предоставляет несколько других значений (также взятых либо из AWS, либо из appSettings.json), но эти другие значения не нужны в ConfigureServices.
строка подключения будет поступать из нескольких мест или только из файла настроек? если только из файла настроек, то нет необходимости в вашем сервисе. получить его непосредственно из IConfiguration и использовать в службах настройки
@Nkosi строка подключения может исходить от AWS Secrets Manager
Тогда я думаю, что это фактический вопрос, который вы должны задать.
@Nkosi, но я уже могу это сделать. Получение строки подключения к БД либо из AWS Secret Manager, либо из appSettings.json уже работает. Проблема в том, что мне нужно, чтобы служба, которая делает это, уже была зарегистрирована (без повторного создания позже), поэтому я могу использовать это значение (откуда оно пришло) для регистрации моего DBContext. См. добавленную строку во фрагменте кода моего исходного сообщения. options.UseMySql(myService.DBConnectionString). Свойство DBConnectionString в MyService вернет правильную строку подключения к БД.





Вызов BuildServiceProvider из ConfigureServices приведет к созданию дополнительной копии одноэлементных сервисов.
Используйте другой подход, который откладывает доступ к поставщику услуг в этом конкретном случае. AddDbContext имеет перегрузку, которая допускает такой случай, когда поставщик услуг предоставляется как часть делегата действия параметров.
//...
services.AddSingleton<IMyService, MyService>();
services.AddDbContext<MyDbContext>((serviceProvider, options) =>
options.UseMySql(serviceProvider.GetRequiredService<IMyService>().DBConnectionString)
);
//....
Ссылка AddDbContext<TContext>(IServiceCollection, Action<IServiceProvider,DbContextOptionsBuilder>, ServiceLifetime, ServiceLifetime)
AddSingleton сообщает Unity построить его один раз. Этот «один раз» является дополнением к любым конструкторам, которые вы вызываете непосредственно в своем коде.
Если вы хотите повторно использовать созданный вами экземпляр, используйте вместо этого AddInstance.
var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetService<IMyService>();
services.AddInstance<IMyService>(myService);
services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));
Можно ли получить экземпляр из serviceProvider перед добавлением IMyService в services?
Потому что им звонят два разных поставщика услуг. Тот, который вы создали вручную в методе настройки служб, и тот, который был создан фреймворком после того, как этот метод вышел за рамки.