创建 ServiceProvider 后是否可以执行代码?
Is it possible to execute code after the ServiceProvider is created?
我有一个 ASP.NET 基于 Core 3.1 WebApi 的项目,它是用 C#
编写的。我想在应用程序完成引导时执行一次代码。
例如,我想在创建 IServiceProvider
后执行以下代码,以避免必须创建 IServiceProvider
.
的第二个实例
我认为在 IServiceCollection
扩展上使用 .AddOptions()
将允许我定义一个函数,稍后将在创建 IServiceProvider
后调用该函数。但好像不是这样。
这是我所做的。在 ConfigureServices(IServiceCollection services)
方法中我添加了以下代码
services.AddOptions()
.Configure<IServiceProvider>((serviceProvider) =>
{
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
});
但是 Configure<IServiceProvider>()
中的代码永远不会被调用。
构建IServiceProvider
后如何调用我的自定义代码?
考虑您的 program.cs
文件。通常,您会在此处看到 .....Build().Run()
代码以启动您的 Web 服务。
如果您拆分构建和 运行 阶段,您可以在服务开始为请求提供服务之前评估服务提供商。
var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).Build();
// Do your initialization here
var serviceProvider = host.Services;
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
// Start your service
host.Run();
如果您已经看过 DefaultServiceProviderFactory 的源代码,那么是的,您可以拥有自己的 ServiceProviderFactory 作为默认值并获得好处 to execute code after the ServiceProvider is created
.
ExampleServiceProviderFactory.cs
public class ExampleServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
{
private readonly ServiceProviderOptions _options;
public ExampleServiceProviderFactory(ServiceProviderOptions options)
{
if (options == null)
throw new ArgumentNullException(nameof(options));
_options = options;
}
public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
{
var serviceProvider = containerBuilder.BuildServiceProvider(_options);
// TODO: here you go
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
return serviceProvider;
}
}
在 statrup 上使用此 ServiceProviderFactory 而不是 DefaultServiceProviderFactory 的更简单快捷的方法是这样的,
Program.cs
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory((context) =>
{
var options = new ServiceProviderOptions()
{
ValidateOnBuild = false, // default,
ValidateScopes = context.HostingEnvironment.IsDevelopment(),
};
return new CustomServiceProviderFactory(options);
})
我有一个 ASP.NET 基于 Core 3.1 WebApi 的项目,它是用 C#
编写的。我想在应用程序完成引导时执行一次代码。
例如,我想在创建 IServiceProvider
后执行以下代码,以避免必须创建 IServiceProvider
.
我认为在 IServiceCollection
扩展上使用 .AddOptions()
将允许我定义一个函数,稍后将在创建 IServiceProvider
后调用该函数。但好像不是这样。
这是我所做的。在 ConfigureServices(IServiceCollection services)
方法中我添加了以下代码
services.AddOptions()
.Configure<IServiceProvider>((serviceProvider) =>
{
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
});
但是 Configure<IServiceProvider>()
中的代码永远不会被调用。
构建IServiceProvider
后如何调用我的自定义代码?
考虑您的 program.cs
文件。通常,您会在此处看到 .....Build().Run()
代码以启动您的 Web 服务。
如果您拆分构建和 运行 阶段,您可以在服务开始为请求提供服务之前评估服务提供商。
var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).Build();
// Do your initialization here
var serviceProvider = host.Services;
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
// Start your service
host.Run();
如果您已经看过 DefaultServiceProviderFactory 的源代码,那么是的,您可以拥有自己的 ServiceProviderFactory 作为默认值并获得好处 to execute code after the ServiceProvider is created
.
ExampleServiceProviderFactory.cs
public class ExampleServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
{
private readonly ServiceProviderOptions _options;
public ExampleServiceProviderFactory(ServiceProviderOptions options)
{
if (options == null)
throw new ArgumentNullException(nameof(options));
_options = options;
}
public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
{
var serviceProvider = containerBuilder.BuildServiceProvider(_options);
// TODO: here you go
var items = serviceProvider.GetServices<ICustomInterface>();
foreach (ICustomInterface item in items)
{
item.DoSome();
}
return serviceProvider;
}
}
在 statrup 上使用此 ServiceProviderFactory 而不是 DefaultServiceProviderFactory 的更简单快捷的方法是这样的,
Program.cs
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory((context) =>
{
var options = new ServiceProviderOptions()
{
ValidateOnBuild = false, // default,
ValidateScopes = context.HostingEnvironment.IsDevelopment(),
};
return new CustomServiceProviderFactory(options);
})