Skip to main content
 首页 » 编程设计

c#之.Net Web Api 2.2 端点中的依赖注入(inject)不可用

2024年01月29日24lidabo

我有一个控制台应用程序,它像 Web API 一样工作。 在 Program.cs 我注册

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

InfoBusinessComponent 还需要一个依赖项注入(inject),我在添加 InfoBusinessComponent 之前就这样做了。我还注册了我的 ILogger。

在我的 InfoController 中,我这样使用 di:

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

当我现在调用该端点时,我会立即收到 500 响应。 当我从 Controller 中删除参数时,进程将进入构造函数和 Controller 。但这不是我想要的。

    public InfoController() 

为什么构造函数没有得到依赖注入(inject)或者为什么没有调用构造函数?

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(); 
    } 
} 

请您参考如下方法:

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

原因: ServiceCollection 不使用任何类型的单例注册表,因此仅通过 ServiceCollection 的某些实例注册服务是不够的,并且构建一些 ServiceProvider 实例。您必须让端点使用您的特定实例 ServiceCollection/ServiceProvider。或者您可以将 ServiceCollection 复制到端点使用的服务集合中 - 这就是我解决它的方法。

那么,让我们使用 ServiceCollection 来注册您的服务(就像现在一样)。然后,我们不用 collection.BuildServiceProvider(),而是在 Startup 中使用 ServiceCollection,将所有注册复制到由管道。

首先,让我们公开您的 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类中,在ConfigureServices()中使用Program.AppServices如下:

编辑:注意 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 ... 
}