Gọi 'BuildServiceProvider' từ mã ứng dụng dẫn đến bản sao cảnh báo Singleton. Làm thế nào để tôi tránh điều này?


8

Tôi vừa dán 4 dòng ở cuối dự án khác và nó hoạt động nhưng tôi nhận được cảnh báo .. Tôi rõ ràng không hiểu rõ về DI đủ ... Nó muốn tôi thay đổi điều gì?

  public void ConfigureServices(IServiceCollection services)
        {
            if (HostingEnvironment.EnvironmentName == "Local")
            {
                services.AddHealthChecksUI()
               .AddHealthChecks()
               .AddCheck<TestWebApiControllerHealthCheck>("HomePageHealthCheck")
               .AddCheck<DatabaseHealthCheck>("DatabaseHealthCheck");
            }

        services.Configure<PwdrsSettings>(Configuration.GetSection("MySettings"));
        services.AddDbContext<PwdrsContext>(o => o.UseSqlServer(Configuration.GetConnectionString("PwdrsConnectionRoot")));

        services.AddMvc(o =>
        {
            o.Filters.Add<CustomExceptionFilter>();
        });

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", b => b
                .SetIsOriginAllowed((host) => true)
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddSwaggerDocument();
        services.AddHttpContextAccessor();

        services.AddAutoMapper(typeof(ObjectMapperProfile));
        services.AddTransient<IEmailSender, EmailSender>();
        services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
        services.AddScoped(typeof(IAsyncRepository<>), typeof(Repository<>));
        services.AddScoped<IRfReportTypeRepository, RfReportTypeRepository>();
        services.AddScoped<IRfReportRepository, RfReportRepository>();
        services.AddScoped<IRfReportLookupsService, RfReportLookupsService>();
        services.AddScoped<IRfReportService, RfReportService>();

        services.Configure<RAFLogging>(Configuration.GetSection("RAFLogging"));
        ServiceProvider serviceProvider = services.BuildServiceProvider(); //WARNING IS HERE
        IOptions<RAFLogging> RAFLogger = serviceProvider.GetRequiredService<IOptions<RAFLogging>>();
        RegisterSerilogLogger logger = new RegisterSerilogLogger(RAFLogger);
    }

2
Đầu tiên, tại sao bạn xây dựng nhà cung cấp? Đây có thể là một vấn đề XY . Bạn có thể định dạng lại câu hỏi để chúng tôi có được một bức tranh rõ ràng hơn về vấn đề hiện tại và những gì bạn đang thực sự cố gắng làm?
Nkosi

Tôi không chắc. Tôi đoán tôi đã có một cái và có lẽ đó là tạo ra cái khác?
punkouter

Bạn có ý nghĩa WARNING IS HEREgì? Vui lòng cung cấp chi tiết về cảnh báo. Cho chúng tôi xem văn bản cảnh báo. Đây có phải là một cảnh báo trình biên dịch? Một cảnh báo từ một số plugin phân tích mã? Nếu vậy thì cái nào? Đây có phải là một ngoại lệ thời gian chạy? Hiển thị cho chúng tôi tất cả các chi tiết có liên quan của ngoại lệ (tin nhắn, loại, theo dõi ngăn xếp, ngoại lệ bên trong).
Steven

@punkouter "Điều gì khiến tôi muốn thay đổi": Đừng xây dựng nhà cung cấp dịch vụ theo cách thủ công bằng cách gọi BuildServiceProvider(). Phương thức này chỉ được gọi bởi Host một lần. Nhà cung cấp dịch vụ trùng lặp có thể dẫn đến một số lỗi không mong muốn.
itminus

Cảnh báo là tiêu đề. Tôi đoán IServiceCollection là nơi tôi nên đặt logger này bằng cách nào đó? Tôi cần hiểu rõ hơn về IServiceCollection so với ServiceProvider.
punkouter

Câu trả lời:


3

Nếu được gọi là BuildServiceProvider () trong ConfigureService, hiển thị cảnh báo "Gọi 'BuildServiceProvider' từ mã ứng dụng dẫn đến một bản sao bổ sung của các dịch vụ Singleton đang được tạo"

tôi đã giải quyết vấn đề này:

Tạo một hàm khác (thông qua đối số là IServiceCollection) và vào hàm gọi BuildServiceProvider ()

nhập mô tả hình ảnh ở đây

Ví dụ mã của bạn phải là:

public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.EnvironmentName == "Local")
        {
            services.AddHealthChecksUI()
           .AddHealthChecks()
           .AddCheck<TestWebApiControllerHealthCheck>("HomePageHealthCheck")
           .AddCheck<DatabaseHealthCheck>("DatabaseHealthCheck");
        }

    services.Configure<PwdrsSettings>(Configuration.GetSection("MySettings"));
    services.AddDbContext<PwdrsContext>(o => o.UseSqlServer(Configuration.GetConnectionString("PwdrsConnectionRoot")));

    services.AddMvc(o =>
    {
        o.Filters.Add<CustomExceptionFilter>();
    });

    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy", b => b
            .SetIsOriginAllowed((host) => true)
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials());
    });

    services.AddSwaggerDocument();
    services.AddHttpContextAccessor();

    services.AddAutoMapper(typeof(ObjectMapperProfile));
    services.AddTransient<IEmailSender, EmailSender>();
    services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
    services.AddScoped(typeof(IAsyncRepository<>), typeof(Repository<>));
    services.AddScoped<IRfReportTypeRepository, RfReportTypeRepository>();
    services.AddScoped<IRfReportRepository, RfReportRepository>();
    services.AddScoped<IRfReportLookupsService, RfReportLookupsService>();
    services.AddScoped<IRfReportService, RfReportService>();

    RegisterSerilogLogger logger = CreateRegisterSerilogLogger(services);
}

private RegisterSerilogLogger CreateRegisterSerilogLogger(IServiceCollection services){
        services.Configure<RAFLogging>(Configuration.GetSection("RAFLogging"));
        ServiceProvider serviceProvider = services.BuildServiceProvider(); //No warning here ))
        IOptions<RAFLogging> RAFLogger = serviceProvider.GetRequiredService<IOptions<RAFLogging>>();
        RegisterSerilogLogger logger = new RegisterSerilogLogger(RAFLogger);
    return logger;
}

Hoặc sử dụng Dịch vụ ứng dụng của IApplicationBuilder. Loại của ApplicationSerivces là IServiceProvider.

CẬP NHẬT :

Tôi đã đề cập giải pháp này là loại bỏ cảnh báo .

Tôi nghĩ phiên bản chính xác là sử dụng thuộc tính ApplicationService của ứng dụng, ứng dụng nào là IApplicationBuilder trong Cấu hình tham số của phương thức. Loại ứng dụng của Dịch vụ là IServiceProvider.

nhập mô tả hình ảnh ở đây


Tôi sẽ thử nó trong thời gian rảnh
Nijat Aliyev

1
Giải pháp tốt đẹp! Tôi đã lo lắng về cảnh báo này (Y)
Samra

7
Gọi phương thức này từ chức năng khác không phải là giải pháp phù hợp. Bạn nên tránh gọi nó từ MỌI NƠI trong mã của bạn. Đây chỉ là loại bỏ cảnh báo.
Adys

@Adys Tôi đồng ý với bạn, bạn của tôi, tôi đã đề cập đến giải pháp này là xóa cảnh báo :) Tôi nghĩ phiên bản chính xác là gọi ServiceProvider của ứng dụng, ứng dụng này là IApplicationBuilder trong phương thức Cấu hình
Ramil Aliyev

-1

Các CHỈ mục đích kêu gọi 'BuildServiceProvider' là để có được một trường hợp cung cấp dịch vụ,

Để xóa cuộc gọi này và vẫn có thể sử dụng IServiceProvider, hãy thay đổi phương thức Configure để lấy nó làm tham số:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider provider)

Bạn không cần tiêm IServiceProvider vì app.ApplicationService là IServiceProvider. - Ramil Aliyev ngày 24 tháng 2 lúc 11:48
Ramil Aliyev
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.