.Net Web Api 2.2终结点中的依赖项注入不可用

时间:2019-07-10 14:08:28

标签: c# asp.net-web-api dependency-injection .net-core

我有一个控制台应用程序,它的工作原理像网络api一样退出。 我在Program.cs上注册

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

在添加InfoBusinessComponent之前,InfoBusinessComponent还需要进行依赖项注入。我还要注册我的ILogger。

在我的InfoController上,我像这样使用di:

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 个答案:

答案 0 :(得分:5)

问题是您用BuildWebHost创建的端点使用了自己的ServiceProvider实例。您创建的ServiceProvider实例不会进入管道。

原因: ServiceCollection不使用任何类型的单例注册表,因此仅通过ServiceCollection的某些实例注册服务并构建{{ 1}}。您必须使端点使用您的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()

编辑:请注意Startup.cs中的using

// 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 ...
}