为什么我的作用域服务每次都被称为新实例?
Why is my scoped service being called as a new instance every time?
这是一个练习 ASP.NET 项目,我用它来更好地理解一些技术,虽然我已经让依赖注入工作了,但它并没有像我想要的那样工作。我有一个 class 想用来存储历史记录,所以每次用户点击提交按钮时,它都会显示一个结果,第二次后它开始显示历史记录。无论如何,我将历史记录作为范围服务添加到 DI,认为这意味着它会被创建,然后在该用户的会话期间保持相同的实例。然而,根据调试器,列表看起来永远不会大于 1,这就是将项目添加到列表的时候。所以代码。
对象
{
public class RollHistory : IRollHistory
{
public List<IRollMessage> Entries { get; set; } = new List<IRollMessage>();
}
}
DI
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddTransient<IDiceTray, DiceTray>();
services.AddTransient<IRollMessage, RollMessage>();
services.AddScoped<IRollHistory, RollHistory>();
}
控制器构造函数
public HomeController(ILogger<HomeController> logger, IDiceTray diceTray, IRollMessage rollMessage, IRollHistory rollHistory)
{
_logger = logger;
_diceTray = diceTray;
_rollMessage = rollMessage;
_rollHistory = rollHistory;
}
以及按钮被点击时的代码
[HttpPost]
public IActionResult Index(DiceRollModel diceRoll)
{
_diceTray.DiceRoll(diceRoll.DiceType, diceRoll.DiceCount, diceRoll.Bonus, diceRoll.VantageType);
_rollMessage.RollMessages(_diceTray);
diceRoll.RollResult = _rollMessage;
_rollHistory.Entries.Add(_rollMessage);
diceRoll.History = _rollHistory.Entries;
return View(diceRoll);
}
值得注意的是,我已经尝试使用和不使用 DI 以至少 4 种不同的方式对此进行编码,唯一可行的方法是使用 AddSingleton,虽然这可能不是问题,因为此应用不太可能永远直播吧,这是不做正确的借口。
我相信“范围”默认是每个请求,这将解释每个提交得到的是自己的服务。
“做正确的事情”当然在某种程度上是见仁见智的。但我的意见显然是我会避免服务器端会话,以避免扩展到多个实例时出现问题。也有支持共享状态的方法,但这很难。对我来说,单身人士也不是代码味道,但他们有自己的问题。
您的问题可能会通过将浏览器中需要的任何状态存储在 cookie 或 localStorage 中来解决。然后,您的服务将具有请求范围,但它会从浏览器读取用户状态,从而导致数据的“用户范围”。 (但不要依赖浏览器状态来保持并记住它对用户是可修改的。)
这是一个练习 ASP.NET 项目,我用它来更好地理解一些技术,虽然我已经让依赖注入工作了,但它并没有像我想要的那样工作。我有一个 class 想用来存储历史记录,所以每次用户点击提交按钮时,它都会显示一个结果,第二次后它开始显示历史记录。无论如何,我将历史记录作为范围服务添加到 DI,认为这意味着它会被创建,然后在该用户的会话期间保持相同的实例。然而,根据调试器,列表看起来永远不会大于 1,这就是将项目添加到列表的时候。所以代码。
对象
{
public class RollHistory : IRollHistory
{
public List<IRollMessage> Entries { get; set; } = new List<IRollMessage>();
}
}
DI
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddTransient<IDiceTray, DiceTray>();
services.AddTransient<IRollMessage, RollMessage>();
services.AddScoped<IRollHistory, RollHistory>();
}
控制器构造函数
public HomeController(ILogger<HomeController> logger, IDiceTray diceTray, IRollMessage rollMessage, IRollHistory rollHistory)
{
_logger = logger;
_diceTray = diceTray;
_rollMessage = rollMessage;
_rollHistory = rollHistory;
}
以及按钮被点击时的代码
[HttpPost]
public IActionResult Index(DiceRollModel diceRoll)
{
_diceTray.DiceRoll(diceRoll.DiceType, diceRoll.DiceCount, diceRoll.Bonus, diceRoll.VantageType);
_rollMessage.RollMessages(_diceTray);
diceRoll.RollResult = _rollMessage;
_rollHistory.Entries.Add(_rollMessage);
diceRoll.History = _rollHistory.Entries;
return View(diceRoll);
}
值得注意的是,我已经尝试使用和不使用 DI 以至少 4 种不同的方式对此进行编码,唯一可行的方法是使用 AddSingleton,虽然这可能不是问题,因为此应用不太可能永远直播吧,这是不做正确的借口。
我相信“范围”默认是每个请求,这将解释每个提交得到的是自己的服务。
“做正确的事情”当然在某种程度上是见仁见智的。但我的意见显然是我会避免服务器端会话,以避免扩展到多个实例时出现问题。也有支持共享状态的方法,但这很难。对我来说,单身人士也不是代码味道,但他们有自己的问题。
您的问题可能会通过将浏览器中需要的任何状态存储在 cookie 或 localStorage 中来解决。然后,您的服务将具有请求范围,但它会从浏览器读取用户状态,从而导致数据的“用户范围”。 (但不要依赖浏览器状态来保持并记住它对用户是可修改的。)