services.AddSingleton, конструктор сервиса никогда не вызывается - PullRequest
1 голос
/ 01 июня 2019

ТЛ; др

services.AddSingleton<ISomeService, SomeService>();
// SomeService not instantiated nor initialized?

В одном из вариантов классического приложения SignalR Chat я отслеживаю изменения в таблице SQL Server и сообщаю о них в режиме реального времени через SignalR. Посмотрите это видео в течение 10 секунд, чтобы понять. Мой код адаптирован из этого проекта . Часть чата работает нормально.

Изменения в таблице SQL Server должны отслеживаться классом SqlDependencyService. Однако его конструктор никогда не называется , и именно здесь он должен получить ссылку на концентратор SignalR.

Вот мой Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddSignalR();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // No instantiation ?!?
    services.AddSingleton<IDatabaseChangeNotificationService, SqlDependencyService>();

    // My lame attempt at forcing instantiation:
    SqlDependencyService sqlDS = serviceProvider.GetService<SqlDependencyService>();
    //sqlDS.Config(); // Fails, sqlDS is null.
}

А вот часть моего класса SqlDependencyService:

public class SqlDependencyService : IDatabaseChangeNotificationService
    {
        private readonly IConfiguration configuration;
        private readonly IHubContext<ChatHub> chatHub;

        // Never gets called!        
        public SqlDependencyService(IConfiguration configuration, IHubContext<ChatHub> chatHub)
        {
            this.configuration = configuration;
            this.chatHub = chatHub;
        }

        // Never gets called!    
        public void Config()
        {
            SubscribeToPersonTableChanges();
        }

        private void SubscribeToPersonTableChanges()
        {
            // ...
        }

        // ...
    }

Вот интерфейс службы:

public interface IDatabaseChangeNotificationService
{
    void Config();
}

Как уже говорилось, конструктор никогда не вызывается. Кроме того, я не понимаю, как можно вызвать метод Config - какое-то волшебное соглашение ASP.NET Core?

У меня нет этой проблемы с HomeController, конструктор которого вызывается и передает IHubContext<ChatHub>:

public class HomeController : Controller
{
    private readonly IHubContext<ChatHub> chatHub;

    public HomeController(IHubContext<ChatHub> chatHub)
    {
        this.chatHub = chatHub;
    }

    // ...
}

1 Ответ

4 голосов
/ 01 июня 2019

Простое добавление сервиса не приведет к его инстанцированию, вам нужно вставить его во что-нибудь, чтобы контейнер вызвал его конструктор.Похоже, вы хотите, чтобы служба была доступна при запуске, поэтому я бы порекомендовал использовать метод Configure при запуске:

public void Configure(IApplicationBuilder app, IDatabaseChangeNotificationService dbService)
{
    dbService.Config();

    //snip
}
...