【问题标题】:Dependency Injection in .Net Web Api 2.2 endpoint not available.Net Web Api 2.2 端点中的依赖注入不可用
【发布时间】:2019-11-20 04:33:02
【问题描述】:

我有一个控制台应用程序,它可以像 web 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();
    }
}

【问题讨论】:

  • 你的 Startup 类是什么样的?我没有看到 appServiceProvider 是如何进入管道的......
  • @felix-b 我将 Startup.cs 添加到我的初始帖子中。你说你看不到我的 appServiceProvider 是如何进入管道的。我假设设置 collection.AddScoped() 足以让软件知道和使用依赖注入对象。
  • 我将在 ConfigureServices 方法中管理我的所有服务......这就是该方法的首要用途

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


【解决方案1】:

问题在于您使用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 中的usings

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

【讨论】:

  • 感谢您的文章菲利克斯!我的服务对象上不存在 TryAdd() 方法。 Add() 也不起作用, AddService() 或类似的东西不存在。所以我不知道如何在启动时添加 AppService。
  • @FrankMehlhop 我猜你错过了一些“使用”,我已经编辑了答案
  • 我是这样做的: public void ConfigureServices(IServiceCollection services) { services.AddRepositories(); services.AddBusinessComponents(); ...并将我的服务放入ServiceExtension。现在它起作用了。我很高兴。非常感谢菲利克斯 B !!! :-)
猜你喜欢
  • 2023-03-03
  • 2019-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多