C# 如何使用依赖项注入(DI)调用类 描述
我想用依赖项注入创建一个类的对象。如果手动设置参数,则会出现异常C# 如何使用依赖项注入(DI)调用类 描述,c#,dependency-injection,blazor,webassembly,blazor-webassembly,C#,Dependency Injection,Blazor,Webassembly,Blazor Webassembly,我想用依赖项注入创建一个类的对象。如果手动设置参数,则会出现异常无法访问已处置的对象。 此应用程序是一个Blazor wasm,具有Dotnet core 3.1。我已经创建了一个应该连接到查询控制台的中间件。所以我有一个包含所有查询客户机的静态列表。如果缺少客户端,将创建该客户端 在中间件中调用异步: Startup.cs public void配置服务(IServiceCollection服务) { services.AddDbContext(选项=> option.UseMySql( Co
无法访问已处置的对象。
此应用程序是一个Blazor wasm,具有Dotnet core 3.1。我已经创建了一个应该连接到查询控制台的中间件。所以我有一个包含所有查询客户机的静态列表。如果缺少客户端,将创建该客户端
在中间件中调用异步:
Startup.cs
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(选项=>
option.UseMySql(
Configuration.GetConnectionString(“DefaultConnection”),
mySqlOptions=>mySqlOptions.ServerVersion(新的System.Version(10,4,13),ServerType.MariaDb)
)
);
services.addScope();
services.addScope();
我试过的
无法访问已处置的对象。对象名称:“IServiceProvider”。
似乎
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>();
另外,此代码可以大大改进,并且仅用于演示目的。看起来它无法工作,因为存储库有EF Dbcontext。我发现此错误=>System.InvalidOperationException:无法解析作用域服务“Microsoft.EntityFrameworkCore.DbContextOptions`1[PhoenixBot.Server.ApplicationDbContext]'来自根提供程序。您可以创建子作用域并将其存储在factory中并使用它。请参阅更新的帖子。根据实际情况,您可能需要根据
TeamspeakInstanceQueryClient
创建作用域。看起来它起了作用。但仅供参考。此工厂创建了一个新的“终生作用域容器”哪一个创建了作用域DI?@LukasGund有作用域的概念。singleton使用服务的根构建。BuildServiceProvider()
,然后它可以创建作用域-通常的情况之一是每个web服务请求一个,每个作用域将共享作用域
服务(所以在作用域内,您将始终获得相同的作用域服务)。当作用域结束时,它将处理所有实现IDIsposable
的实例化作用域服务和临时服务(一般情况下,其他一些容器也可能具有不同的行为)。为什么您的TeamspeakInstanceQueryClient
类创建InstancesControlRepository
的实例,而不是简单地在DI容器中注册InstancesControlRepository
,并让它处理初始化类型?您是说在ClientFactory中?
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();
}
}
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>();
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>();
var factory = serviceProvider.GetRequiredService<ClientFactory>();
queryClient = factory.Create();