首页 > 解决方案 > 我应该处理 IServiceProvider 提供的瞬态对象还是垃圾收集器处理它?

问题描述

我正在构建一个锦标赛应用程序,其中当然有很多锦标赛可以玩。我从 ASP.NET Core 3.1 中的内置依赖注入中获取了一个 TournamentStore 对象。

在 Startup.cs 的 ConfigureServices 方法中,我设置了一个临时服务:

services.AddTransient<ITournamentStore, TournamentStore>();

我通过在 TournamentService 类的构造函数中注入 IServiceProvider 来获得该服务:

public class TournamentService : ITournamentService
{
    private readonly IServiceProvider _serviceProvider;

    public TournamentService(
        IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task<ITournamentStore> GetRandomTournamentAsync(DateTime startTime)
    {
        var tournament = (ITournamentStore)_serviceProvider.GetService(typeof(ITournamentStore));
        // add tournament details...

在 TournamentStore (我从 IServiceProvider 获得的服务)中,我正在使用 System.Timers.Timer 应该被处理:

public class TournamentStore : ITournamentStore, IAsyncDisposable, IDisposable
{
    private Timer _timer;

    private readonly ITournamentsStore _tournaments;
    private readonly IHubContext<GameHub, IGameClient> _hubContext;
    private readonly IMapper _mapper;

    public TournamentStore(
        ITournamentsStore tournaments,
        IHubContext<GameHub, IGameClient> hubContext,
        IMapper mapper)
    {
        _tournaments = tournaments;
        _hubContext = hubContext;
        _mapper = mapper;
    }

    public string PublicId { get; set; } = Guid.NewGuid().ToString();
    public string Name { get; set; }
    public string Category { get; set; }
    public int? CategoryId { get; set; }
    public string Type { get; set; }
    public string TypeId { get; set; }
    public string Difficulty { get; set; }
    public string DifficultyId { get; set; }
    public List<QuestionModel> Questions { get; set; }
    public int NumberOfQuestions => Questions.Count();
    public int SecondsPerQuestion { get; set; } = 15;
    public int CurrentQuestion { get; set; } = 0;
    public bool Finshed => CurrentQuestion > Questions.Count();
    public bool Public { get; set; }
    public DateTime StartTime { get; set; }
    public string StartTimeWithTimeZone => StartTime.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
    public DateTime? EndTime { get; set; }
    public List<Player> Players { get; set; }
    public int NumberOfPlayers => Players.Count();

    public void SetTournamentStartTimer()
    {
        var difference = StartTime - DateTime.UtcNow;
        _timer = new Timer(difference.TotalMilliseconds);
        _timer.Elapsed += async (sender, e) => await StartTournamentAsync();
        _timer.Start();
    }

    private async Task StartTournamentAsync()
    {
        // some logic to start tournament

    }

    public ValueTask DisposeAsync()
    {
        throw new NotImplementedException();
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

所以我想知道我应该在 DisposeAsync 方法中处理完整对象还是只处理 Timer 并让垃圾收集器处理 TournamentStore 对象?如您所见,TournamentStore 对象由多个属性和两个对象列表组成,所以如果我要处理 TournamentStore 对象,是否应该将这些列表设置为 null?如果没有足够的玩家或锦标赛结束,将从对象本身调用 DisposeAsync。

标签: c#asp.net-core

解决方案


向服务提供者请求 ITournamentStore 的类不知道对象的范围(单例、瞬态等),因此 TournamentStore 的处置应由 ServiceProvider 管理。

TournamentStore 的所有可处置属性都应在 TournamentStore 处置中处置。无需将所有属性设置为空。

我建议不要同时实现接口 IDisposable 和 IAsyncDisposable。Dispose 或 DisposeAsync 方法旨在由创建 TournamentStore 的对象调用(此处为 ServiceProvider)。

我建议使用如下实现:

private async Task<ITournament> StartTournamentAsync()

ITournament : IAsyncDisposable

推荐阅读