添加瞬态不会为每个请求创建一个新实例吗?



我在玩依赖注入设计模式,在这种模式中存在一个短暂的生存期,它在每个请求上创建一个新对象。然而,当我尝试将它应用于C#的启动示例WebApi时,它似乎并没有像预期的那样工作。例如,它生成相同的随机数,而原始请求在每个请求上生成一个随机整数。我有两个问题

  1. 为什么它没有像我预期的那样运行
  2. 容器如何知道WeatherForecastController类需要一个类型为IWeatherForecast的实例,该实例为用于IEnumerable<IWeatherForecast> Get()方法?否则,我会得到以下错误

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

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

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,仅注册

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

它确实按预期工作。

两个请求会给你不同的结果:

请求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"
}
]

请求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"
}
]

对于瞬态生命周期,每次请求时都会创建一个新对象,而这正是正在发生的事情。您在构造函数中只请求一次,因此每次创建一个控制器实例时只创建一个实例。您看到相同的对象重复了5次,因为您在行上使用了相同的实例:

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

您不是在上面的行中请求IWeatherForecast,而是在构造函数中使用您请求的实例。

如果WeatherForecastController如在其构造函数上所述具有IWeatherForecast的依赖关系。IWeatherForecast必须注册到集装箱中

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

否则你会得到错误:

System.InvalidOperationException:无法解析类型的服务尝试激活时出现"WebApplication2.IWeatherForecast"'WebApplication2.Controllers.WeatherForecastController'

依赖注入基础结构知道控制器,因为您使用注册了它

builder.Services.AddControllers();

通过使用反射检查控制器构造函数,它知道它依赖于IWeatherForecast

相关内容

最新更新