Внедрение зависимостей в конечной точке .Net Web Api 2.2 недоступно - PullRequest
1 голос
/ 10 июля 2019

У меня есть консольное приложение, которое работает, как веб-API. На Program.cs я регистрируюсь

var collection = new ServiceCollection();
collection.AddScoped<IInfoBusinessComponent, InfoBusinessComponent>();

Для InfoBusinessComponent также требуется внедрение зависимостей, которое я делаю перед добавлением InfoBusinessComponent. Также я регистрирую свой ILogger.

В моем инфо-контроллере я использую ди так:

public InfoController(IInfoBusinessComponent businessComponent, ILogger<InfoController> logger)

Когда я звоню сейчас этой конечной точке, я сразу получаю 500 ответов. Когда я стираю аргументы из контроллера, чем процесс идет в конструктор и контроллер. Но это не то, что я хочу.

    public InfoController()

Почему конструктор не получает инъекцию зависимости или почему конструктор не вызывается?

public class Program
{
    #region fields and propetries
    public IConfiguration Configuration { get; }  
    //# if DEBUG
    //#endif
    public static IConnection Connection { get; set; }
    public static ITimeSeriesBusinessComponent TimeSeriesBusinessComponent { get; set; }
    public static IInfoBusinessComponent InfoBusinessComponent { get; set; }
    private static int counter;
    #endregion fields and propetries

    public static void Main(string[] args)
    {
        IConfiguration config = GetConfigurations();
        ILogger logger = GetLogger();
        ServiceProvider appServiceProvider = GetServiceProvider(config);

        Parallel.Invoke
        (
            () =>
            {
                BuildWebHost(args).Build().Run();
            }, 
            () =>
            {
                //...
            }
        );


    }

    private static IConfiguration GetConfigurations()
    {
        var builder = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json");

        IConfiguration config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true)
            .Build();
        return config;
    }

    private static ILogger GetLogger()
    {
        ILogger logger = new LoggerFactory().AddNLog().CreateLogger<Program>();
        return logger;
    }

    private static ServiceProvider GetServiceProvider(IConfiguration config)
    {
        var collection = new ServiceCollection();
        collection.AddLogging(configuration => configuration.AddNLog());
        //...
        collection.AddScoped<IInfoRepository>(serviceProvider =>
        {
            return new InfoRepository(
                config["ConnectionStrings:MainConnection"], 
                config["ConnectionStrings:MetaDataConnection"],
                config["InfoFunctionName"],
                config["UserName"],
                config["Password"],
                config["VirtualHost"],
                config["ConnectionHostName"]);
        });
        collection.AddScoped<IInfoBusinessComponent, InfoBusinessComponent>();
        var appServiceProvider = collection.BuildServiceProvider();
        return appServiceProvider;
    }

    public static IWebHostBuilder BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .UseUrls("http://0.0.0.0:5003")
            .UseNLog();
}

Вот Startup.cs:

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info
            {
                Title = "My CLI"
            });
        });
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My CLI");
            c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);
            c.RoutePrefix = string.Empty;
        });

        app.UseMvc();
    }
}

1 Ответ

5 голосов
/ 10 июля 2019

Проблема в том, что конечная точка, которую вы создаете с помощью BuildWebHost, использует свой собственный экземпляр ServiceProvider. Созданный вами экземпляр ServiceProvider не попадает в конвейер.

Почему: ServiceCollection не использует какой-либо одноэлементный реестр, поэтому недостаточно зарегистрировать службы через некоторый экземпляр ServiceCollection и создать какой-то экземпляр ServiceProvider. Вы должны заставить конечную точку использовать ваш конкретный экземпляр ServiceCollection / ServiceProvider. Или вы можете скопировать свой ServiceCollection в тот, который используется конечной точкой - так я бы решил.

Итак, давайте используем ServiceCollection для регистрации ваших сервисов (как сейчас). Затем вместо collection.BuildServiceProvider() давайте использовать ServiceCollection в Startup, чтобы скопировать все регистрации в коллекцию сервисов, используемую конвейером.

Во-первых, давайте выставим ваш ServiceCollection доступным с Startup:

class Program
{
    public static ServiceCollection AppServices { get; set; }

    public static void Main(string[] args)
    {
        // ...other stuff...

        AppServices = GetServiceCollection(config);

        // ...other stuff...
    }

    // renamed from GetServiceProvider
    private static ServiceCollection GetServiceCollection(IConfiguration config)
    {
        var collection = new ServiceCollection();

        // ... register services...

        return collection;
    }
}

Затем в классе Startup используйте Program.AppServices в ConfigureServices() следующим образом:

РЕДАКТИРОВАТЬ : обратите внимание на using s в Startup.cs

// make sure these usings are present:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

....

public class Startup
{
    // ... other members ...

    public void ConfigureServices(IServiceCollection services)
    {
        // ... the usual stuff like services.AddMvc()...

        // add this line:
        services.TryAdd(Program.AppServices);
    }

    // ... other members ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...