如何使用依赖注入 (DI) 调用类

卢卡斯·冈德

描述

我想用依赖注入创建一个类的对象。如果我手动设置参数,则会出现异常Cannot access a disposed of the object.

此应用程序是带有 Dotnet 核心 3.1 的 Blazor wasm。我创建了一个应该连接到查询控制台的中间件。所以我有一个包含所有查询客户端的静态列表。如果缺少客户端,则会创建它。

在中间件中调用 Async:

public async Task InvokeAsync(HttpContext context,
    IConfiguration configuration,
    IInstanceControlRepository instanceControlRepository,
    IServiceProvider serviceProvider)
{
    _configuration = configuration;
    _instanceControlRepository = instanceControlRepository;

    long timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
    var instances = _instanceControlRepository.GetAllInstances();

    if (_time + 3 <= timestamp)
    {
        _time = timestamp;

        // Remove
        foreach(var client in TeamspeakInstanceQueryClients.ToList())
        {
            var cl = instances.ToList().Find(el => el.Id == client.Instance.Id);
            
            if(cl == null)
            {
                client.Dispose();
                TeamspeakInstanceQueryClients.RemoveAll(el => el.Instance.Equals(client.Instance));
            }
        }   

        // Create & Update
        foreach (var instance in instances)
        {
            var queryClient = TeamspeakInstanceQueryClients.Find(el => el.Instance.Id == instance.Id);

            if(queryClient == null)
            {
                //var test = ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider);
                //var dbContext = serviceProvider.GetService<ApplicationDbContext>();
                //queryClient = new TeamspeakInstanceQueryClient(new InstancesControlRepository(ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider)));
                queryClient = new TeamspeakInstanceQueryClient(serviceProvider);
                _ = queryClient.Connect(instance);
                TeamspeakInstanceQueryClients.Add(queryClient);
            }
            else
            {
                _ = queryClient.CheckInstanceData(instance);
            }
        }
    }

    await _next(context);
}

TeamspeakInstanceQueryClient.cs

public partial class TeamspeakInstanceQueryClient : ITeamspeakInstanceQueryClient
{
    private IInstanceControlRepository _instanceControlRepository;

    private const short MAX_RETRYS = 3;
    private const short TIME_TO_RETRY = 10;

    private EventHandler OnConnected;

    public Instance Instance { get; internal set; }
    public TeamSpeakClient Client { get; internal set; }
    public bool IsSelected { get; internal set; }
    private short _connectionTrys = 0;

    public TeamspeakInstanceQueryClient(IServiceProvider serviceProvider)
    {
        _instanceControlRepository = new InstancesControlRepository(ActivatorUtilities.CreateInstance<ApplicationDbContext>(serviceProvider));
        Init();
    }
}

InstancesControlRepository.cs

public class InstancesControlRepository : IInstanceControlRepository
{
    private readonly ApplicationDbContext _applicationDbContext;

    public InstancesControlRepository(ApplicationDbContext applicationDbContext)
    {
        _applicationDbContext = applicationDbContext;
    }
}

启动文件

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(option =>
        option.UseMySql(
            Configuration.GetConnectionString("DefaultConnection"),
            mySqlOptions => mySqlOptions.ServerVersion(new System.Version(10, 4, 13), ServerType.MariaDb)
        )
    );
    services.AddScoped<IInstanceControlRepository, InstancesControlRepository>();
    services.AddScoped<IServerQueryRepository, ServerQueryRepository>();

我试过的

  1. 我试图用服务提供者创建类,但它遇到了同样的错误
  2. 我试图在创建的类中使用服务提供者创建缺少的参数。但我需要注入也会创建异常的服务提供者Cannot access a disposed of the object. Object name: 'IServiceProvider'.
  3. 我试图使服务提供者静态,所以它不能被处理,但它被处理了。
古鲁·斯特朗

似乎实例IServiceProvider一个作用域,它在作用域结束时被处理(在我假设的请求结束时)。您可以尝试为您定义单例工厂TeamspeakInstanceQueryClient并使用它:

class ClientFactory
{
    private IServiceProvider _sp { get; set; }        
    private IServiceScope _scope  { get; set; }
    public  MyClass(IServiceProvider sp)
    {
        _sp = sp;
        _scope = sp.CreateScope();
    }
    public TeamspeakInstanceQueryClient Create() => new TeamspeakInstanceQueryClient(_scope.ServiceProvider);
}

// register it as singleton 
services.AddSingleton<ClientFactory>();

并将其用于InvokeAsync

var factory = serviceProvider.GetRequiredService<ClientFactory>();
queryClient = factory.Create();

PS 此代码可以大大改进,仅用于演示目的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章