简体   繁体   English

AddTransient 不会为每个请求创建一个新实例吗?

[英]Doesn't AddTransient create a new instance per request?

I am toying with the dependency injection design pattern in which there exists a transient lifetime which creates a new object on each request.我正在玩弄依赖注入设计模式,其中存在一个短暂的生命周期,它在每个请求上创建一个新的 object。 However, when I try to apply it to C#'s startup example, WebApi, it doesn't seem to work as expected.但是,当我尝试将它应用于 C# 的启动示例 WebApi 时,它似乎没有按预期工作。 For example, it generates the same random number while the original generates a random integer on each request.例如,它生成相同的随机数,而原始版本在每次请求时生成随机数 integer。 I have two questions that我有两个问题

  1. Why doesn't it run as I expect?为什么它没有像我预期的那样运行?
  2. How is the container aware of WeatherForecastController class needs an instance, whose type is of IWeatherForecast , which is used in IEnumerable<IWeatherForecast> Get() method?容器如何知道WeatherForecastController class 需要一个类型为IWeatherForecast的实例,该实例在IEnumerable<IWeatherForecast> Get()方法中使用? Otherwise, I get the following error,否则,我会收到以下错误,

System.InvalidOperationException: Unable to resolve service for type 'WebApplication2.IWeatherForecast' while attempting to activate 'WebApplication2.Controllers.WeatherForecastController'.

WeatherForecastController.cs WeatherForecastController.cs

using Microsoft.AspNetCore.Mvc;

namespace WebApplication2.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private readonly IWeatherForecast _weatherForecast;
    
    public WeatherForecastController(IWeatherForecast weatherForecast)
    {
        _weatherForecast = weatherForecast;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<IWeatherForecast> Get()
    {
        var returnValue= Enumerable.Range(1, 5).Select(index => _weatherForecast).ToArray();

        return returnValue;
        
        /*
         nearly original one, working as expected
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = "testing"
            })
            .ToArray();
        */
        
    }
}

WeatherForecast.cs天气预报.cs

namespace WebApplication2;

public class WeatherForecast : IWeatherForecast
{
    public WeatherForecast()
    {
        Date = DateTime.Now.AddDays(0);
        TemperatureC = Random.Shared.Next(-20, 55);
        Summary = "testing";
    }

    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public string? Summary { get; set; }
    public int TemperatureF() => 32 + (int)(TemperatureC / 0.5556);

}

public interface IWeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public string? Summary { get; set; } 
    public int TemperatureF();
}

Program.cs, registering only Program.cs,仅注册

...
builder.Services.AddTransient<IWeatherForecast, WeatherForecast>();
...

It works as expected indeed.它确实按预期工作。

Two requests give you different results:两个请求给你不同的结果:

Request 1:请求 1:

[
  {
    "date": "2022-10-09T09:01:36.408982+02:00",
    "temperatureC": 4,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:01:36.408982+02:00",
    "temperatureC": 4,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:01:36.408982+02:00",
    "temperatureC": 4,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:01:36.408982+02:00",
    "temperatureC": 4,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:01:36.408982+02:00",
    "temperatureC": 4,
    "summary": "testing"
  }
]

Request 2:请求 2:

[
  {
    "date": "2022-10-09T09:02:01.6052197+02:00",
    "temperatureC": 46,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:02:01.6052197+02:00",
    "temperatureC": 46,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:02:01.6052197+02:00",
    "temperatureC": 46,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:02:01.6052197+02:00",
    "temperatureC": 46,
    "summary": "testing"
  },
  {
    "date": "2022-10-09T09:02:01.6052197+02:00",
    "temperatureC": 46,
    "summary": "testing"
  }
]

With transient lifetime a new object is created each time you request it, and this is exactly what is happening.对于短暂的生命周期,每次您请求时都会创建一个新的 object,而这正是正在发生的事情。 You are requesting it only once in the constructor so only one instance is created each time one controller instance is created.您在构造函数中只请求一次,因此每次创建一个 controller 实例时只创建一个实例。 You see the same object repeated 5 times because you use the same instance on the line:您看到相同的 object 重复了 5 次,因为您在该行中使用了相同的实例:

var returnValue = Enumerable.Range(1, 5).Select(index => _weatherForecast).ToArray();

You are not requesting IWeatherForecast on the above line, you are using the instance you requested on the constructor.您没有在上面的行中请求IWeatherForecast ,您正在使用您在构造函数中请求的实例。

If WeatherForecastController has a dependency of IWeatherForecast as stated on its constructor.如果WeatherForecastController具有IWeatherForecast的依赖项,如其构造函数中所述。 IWeatherForecast must be registered into the container IWeatherForecast必须注册到容器中

builder.Services.AddTransient<IWeatherForecast, WeatherForecast>();

Otherwise you get the error:否则你会得到错误:

System.InvalidOperationException: Unable to resolve service for type 'WebApplication2.IWeatherForecast' while attempting to activate 'WebApplication2.Controllers.WeatherForecastController' System.InvalidOperationException:尝试激活“WebApplication2.Controllers.WeatherForecastController”时无法解析类型“WebApplication2.IWeatherForecast”的服务

The dependency injection infrastructure knows about the controller because you registered it using:依赖注入基础结构知道 controller 因为您使用以下方式注册了它:

builder.Services.AddControllers();

And it knows it depends on IWeatherForecast by inspecting the controller constructor using reflection.通过使用反射检查 controller 构造函数,它知道它依赖于IWeatherForecast

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 每个请求创建全新的 HttpClient 是否便宜 - Is it cheap to create brand new HttpClient per request 在Java中创建T的新实例 - Create new instance of T in Java &quot;添加选项<T> .Configure()”在“services.AddTransient”时不起作用<IConfigureOptions<T> ,ConfigureTOptions&gt;()”呢? - "AddOptions<T>.Configure()" doesn't work when "services.AddTransient<IConfigureOptions<T>, ConfigureTOptions>()" does? 在没有新约束的情况下创建T的新实例 - Create a new instance of T without the new constraint NLog为类的每个实例创建新的日志文件 - NLog create new log file per instance of class 不满足 <Texture2D> ()创建一个新实例? - Doesn't Content.Load<Texture2D>() create a new instance? 如何使用autofac并解析新实例,并忽略每个请求注册单个实例或实例? - How to use autofac and resolve new instance and ignore register single or instance per request? EF 7(核心)。 像AddTransient一样创建DBContext - EF 7 (Core). Create DBContext like AddTransient PRISM-为每个交互请求创建一个新的对话框实例- - PRISM - Create a new dialog instance to each interaction request - asp.net Web服务器是否按请求运行Web应用程序的新实例? - Does an asp.net web-server run a new instance of a web application per request?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM