【发布时间】:2020-04-24 23:25:27
【问题描述】:
我无法弄清楚为什么我的依赖注入没有按预期工作,当我的控制器被击中时,MyFirstService 的构造函数再次被击中,因此我击中了一个与我希望的不同的取消标记当调用StopFeeds() 方法时。
我尝试将控制器添加为单例并使用控制器的 StartFeed() 方法来实例化该类,但无论我对 DI 做什么(通用 ctor DI、显式属性分配、[FromServices] 甚至直接传递在服务集合中)当我点击停止提要时,它将创建另一个 MyFirstService 实例......有什么想法吗?
界面:
public interface IFirstService : IService
{
OrderDto CreateOrder(Order order);
Task<string> ProcessOrder(string orderXml);
void ProcessLineItems(ref List<NewLineItem> items, ref int lineNum, Item i, string orderId);
NewOrderEvent NewOrderEvent(OrderDto newOrder, Order order, List<NewLineItem> lineItems);
}
我的第一服务:
public class MyFirstService : IFirstService
{
private SftpService _sftpService;
private readonly ITimer<MyService> _timer;
private readonly IMediator _mediator;
private readonly ILogger<MyService> _logger;
private readonly MyFirstConfig _iOptions;
private CancellationTokenSource CancellationTokenSource;
public MyService(IMediator mediator, ILogger<MyService> logger, IOptionsSnapshot<MyFirstConfig> iOptions)
{
_mediator = mediator;
_timer = new Timer<MyFirstService>(logger);
_logger = logger;
_iOptions = iOptions.Value;
CancellationTokenSource = new CancellationTokenSource();
CancellationTokenSource.Token.Register(FeedStopped);
}
private void CreateSftpService()
{
_sftpService = new SftpService(_iOptions.SftpOptions);
}
public void StartFeed()
{
CreateSftpService();
StartFeed(TimerSchedule);
}
public void StartFeed(TimeSpan timeSpan)
{
_timer.ScheduleCallback(timeSpan, ProcessOrderFeedAsync, CancellationTokenSource.Token);
}
public void StopFeed()
{
CancellationTokenSource.Cancel();
_sftpService.Dispose();
}
启动:
services.Configure<MyFirstConfig>(Configuration.GetSection("FirstSection"));
services.Configure<MySecondConfig>(Configuration.GetSection("SecondSection"));
services.AddSingleton<IFirstService, MyFirstService>();
services.AddSingleton<ISecondService, MySecondService>();
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<IFirstService>().StartFeed();
serviceProvider.GetRequiredService<ISecondService>().StartFeed();
控制器:(我确实处理其他状态代码,我去掉了 try/catch,因为它们无关紧要)
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using System.Threading.Tasks;
using SFTP.Services;
using System;
namespace API.Controllers
{
[Route("api/[controller]/")]
[ApiController]
public class MyController : Controller
{
[HttpPost]
[Route("feeds/start")]
public IActionResult StartFeed([FromServices] IFirstService myService)
{
myService.StartFeed();
return Ok();
}
[HttpPost]
[Route("feeds/stop")]
public IActionResult StopFeed([FromServices] IFirstService myService)
{
myService.StopFeed();
return Ok();
}
}
}
【问题讨论】:
-
我在这里看不到任何明显的东西。 在调用
AddSingleton之后,你有错误的AddScoped或AddTransientISubService吗? -
@Mayo 我添加了 start feed,它创建了
sftpService的本地副本,在调用stopFeed()时将其处理掉 -
@KirkLarkin 我不这么认为,但我会再次完成启动并密切关注 Scoped 或 Transient 分配
-
如果您想要长期运行的服务,您应该将其注册为 background 托管服务。检查Background tasks with hosted services in ASP.NET Core。您如何确定构造函数被调用了两次?构造函数中没有记录
-
你怎么知道它是一个不同的实例?尝试使用 GUID 设置私有字段并在调试时检查该字段以查看它是否实际上是不同的实例。
标签: c# asp.net-core dependency-injection asp.net-core-2.2