新范围内的服务就像瞬态服务
Services in new scope act like transient services
我有一个方法,我需要一个新的范围(必须是一个新的范围,这里的场景不需要它,但是当这个工作时,我会在其他需要单独范围的地方使用逻辑),为此我使用 IServiceScopeFactory(我认为这是正确的)。然后我从新的范围中获得我需要的服务,我希望它们仍然以范围内的方式工作。但是这些服务中的依赖关系就像瞬态服务一样。我总是在构造函数中得到一个新的。
示例:
public class EntryController : IEntryController
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IRequestContext _requestContext;
public EntryController(IServiceScopeFactory scopeFactory, IRequestContext requestContext)
{
_scopeFactory = scopeFactory;
_requestContext = requestContext;
}
public async Task GetEntries(int userId)
{
using var scope = _scopeFactory.CreateScope();
var requestContext = scope.ServiceProvider.GetRequiredService<IRequestContext>();
var manager = scope.ServiceProvider.GetRequiredService<IEntryManager>();
var test = requestContext // Completely new IRequestContext
requestContext = _requestContext;
var test1 = requestContext // test1 is the same as _requestContext, which is good
return await manager.GetAll();
}
}
public class EntryManager : IEntryManager
{
private readonly IEntryResource _entryResource;
private readonly IRequestContext _requestContext;
public EntryManager (IEntryResource entryResource, IRequestContext requestContext)
{
_entryResource = entryResource;
_requestContext = requestContext;
}
public async Task GetAll()
{
var test = _requestContext; // Completely new IRequestContext, which is bad
return await _entryResource.GetAll();
}
}
public class EntryResource : IEntryResource
{
private readonly IRequestContext _requestContext;
public EntryManager (IRequestContext requestContext)
{
_requestContext = requestContext;
}
public async Task GetAll()
{
var test = _requestContext; // Completely new IRequestContext, which is bad
// here is some code for the db query where I need info stored in the IRequestContext
return _dbContext.Entries.ToListAsync();
}
}
我理解为什么我在新范围内获得一个新的 requestContext,但是当我更新值时,我希望这些值通过依赖注入在整个范围内可用。当我 运行 没有新范围的代码时,一切正常。所有服务都在启动时作为作用域服务添加。
services.AddScoped<IRequestContext, RequestContext>();
services.AddScoped<IEntryManager,EntryManager>();
services.AddScoped<IEntryResource, EntryResource>();
我发现了问题:
requestContext = _requestContext;
这没有用,因为 requestContext
不再是该行之前的同一个对象,并且它将不再与注入到范围内其他服务的对象相同。
如果我只是为其属性分配新值,它就可以工作。
这就是它起作用的原因:
requestContext.Id = _requestContext.Id
这样它仍然是同一个对象,Id
的新值可以在 requestContext
.
的新范围内的任何地方检索到
使用自定义扩展我可以分配所有属性。
public static IRequestContext CopyRC(this IRequestContext dest, IRequestContext source)
{
var props = typeof(RequestContext).GetProperties();
foreach(var prop in props)
{
var value = prop.GetValue(source);
prop.SetValue(dest, value);
}
return dest;
}
有了这个
requestContext = _requestContext;
现在变成了
requestContext.CopyRC(_requestContext);
感谢 Stephen Cleary 通过他的工作片段帮助我寻找正确的方向。
我有一个方法,我需要一个新的范围(必须是一个新的范围,这里的场景不需要它,但是当这个工作时,我会在其他需要单独范围的地方使用逻辑),为此我使用 IServiceScopeFactory(我认为这是正确的)。然后我从新的范围中获得我需要的服务,我希望它们仍然以范围内的方式工作。但是这些服务中的依赖关系就像瞬态服务一样。我总是在构造函数中得到一个新的。
示例:
public class EntryController : IEntryController
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IRequestContext _requestContext;
public EntryController(IServiceScopeFactory scopeFactory, IRequestContext requestContext)
{
_scopeFactory = scopeFactory;
_requestContext = requestContext;
}
public async Task GetEntries(int userId)
{
using var scope = _scopeFactory.CreateScope();
var requestContext = scope.ServiceProvider.GetRequiredService<IRequestContext>();
var manager = scope.ServiceProvider.GetRequiredService<IEntryManager>();
var test = requestContext // Completely new IRequestContext
requestContext = _requestContext;
var test1 = requestContext // test1 is the same as _requestContext, which is good
return await manager.GetAll();
}
}
public class EntryManager : IEntryManager
{
private readonly IEntryResource _entryResource;
private readonly IRequestContext _requestContext;
public EntryManager (IEntryResource entryResource, IRequestContext requestContext)
{
_entryResource = entryResource;
_requestContext = requestContext;
}
public async Task GetAll()
{
var test = _requestContext; // Completely new IRequestContext, which is bad
return await _entryResource.GetAll();
}
}
public class EntryResource : IEntryResource
{
private readonly IRequestContext _requestContext;
public EntryManager (IRequestContext requestContext)
{
_requestContext = requestContext;
}
public async Task GetAll()
{
var test = _requestContext; // Completely new IRequestContext, which is bad
// here is some code for the db query where I need info stored in the IRequestContext
return _dbContext.Entries.ToListAsync();
}
}
我理解为什么我在新范围内获得一个新的 requestContext,但是当我更新值时,我希望这些值通过依赖注入在整个范围内可用。当我 运行 没有新范围的代码时,一切正常。所有服务都在启动时作为作用域服务添加。
services.AddScoped<IRequestContext, RequestContext>();
services.AddScoped<IEntryManager,EntryManager>();
services.AddScoped<IEntryResource, EntryResource>();
我发现了问题:
requestContext = _requestContext;
这没有用,因为 requestContext
不再是该行之前的同一个对象,并且它将不再与注入到范围内其他服务的对象相同。
如果我只是为其属性分配新值,它就可以工作。 这就是它起作用的原因:
requestContext.Id = _requestContext.Id
这样它仍然是同一个对象,Id
的新值可以在 requestContext
.
使用自定义扩展我可以分配所有属性。
public static IRequestContext CopyRC(this IRequestContext dest, IRequestContext source)
{
var props = typeof(RequestContext).GetProperties();
foreach(var prop in props)
{
var value = prop.GetValue(source);
prop.SetValue(dest, value);
}
return dest;
}
有了这个
requestContext = _requestContext;
现在变成了
requestContext.CopyRC(_requestContext);
感谢 Stephen Cleary 通过他的工作片段帮助我寻找正确的方向。