.net 核心注入和解析服务
.net core injecting and resolving services
我正在尝试 .net 核心 Web api。我创建了一个静态方法来像这样注册我的控制器:
public static class RegistrationExtensions
{
public static void RegisterApplicationServices(this IServiceCollection services, IServiceProvider serviceProvider)
{
services.RegisterSingletons();
services.RegisterRequests();
services.RegisterTransient(serviceProvider);
}
public static void RegisterSingletons(this IServiceCollection services)
{
services.AddSingleton<Configuration>();
}
public static void RegisterRequests(this IServiceCollection services)
{
services.AddScoped<ISettingsService, SettingsService>();
}
public static void RegisterTransient(this IServiceCollection services, IServiceProvider serviceProvider)
{
var config = serviceProvider.GetService<Configuration>();
services.AddDbContext<InteractiveChoicesContext>(m => m.UseSqlServer(config.ConnectionString));
}
}
如您所见,我想解析我的 Configuration class,其中包含我传入的 ConnectionString DbContext。
请解决 Configuration 我试图使用 IServiceProvider 注入到 RegisterApplicationServices 方法中。
为了调用此方法,我将 Startup class 的 ConfigureServices 更改为:
public void ConfigureServices(IServiceCollection services, IServiceProvider serviceProvider)
{
services.AddMvc();
services.RegisterApplicationServices(serviceProvider);
}
但是当我 运行 我的应用程序时,我得到一个错误:
The ConfigureServices method must either be parameterless or take only one parameter of type IServiceCollection.
错误很明显。我的问题是:如何在我的 RegisterTransient 方法中解决 Configuration class?
如果您必须使用您自己的配置 class 而不是使用 IConfiguration
,您可以这样做来解决您目前配置的 IServiceCollection
,在您的情况下已经有注册您的 Configuration
单身人士:
public static void RegisterTransient(this IServiceCollection services)
{
// Use services registered so far
var serviceProvider = services.BuildServiceProvider();
var config = serviceProvider.GetRequiredService<Configuration>();
services.AddDbContext<InteractiveChoicesContext>(m => m.UseSqlServer(config.ConnectionString));
}
其中 BuildServiceProvider()
是程序集 Microsoft.Extensions.DependencyInjection
、命名空间 Microsoft.Extensions.DependencyInjection
中的扩展方法。
实际上有一个 AddDbContext
的重载,它需要一个 Action<IServiceProvider, DbContextOptionsBuilder>
,这应该正是您要查找的内容。
例如:
services.AddDbContext<InteractiveChoicesContext>((provider, options) =>
{
var config = provider.GetService<Configuration>();
options.UseSqlServer(config.ConnectionString);
});
我已经用 v2、v3 和 v5 对此进行了测试。 EF Core 2.0.0 中指定的此重载的文档被逐字包含以供后代和相关性使用
//
// Summary:
// Registers the given context as a service in the
// Microsoft.Extensions.DependencyInjection.IServiceCollection.
// You use this method when using dependency injection in your application, such
// as with ASP.NET. For more information on setting up dependency injection, see
// http://go.microsoft.com/fwlink/?LinkId=526890.
// This overload has an optionsAction that provides the applications
// System.IServiceProvider.
// This is useful if you want to setup Entity Framework to resolve its internal
// services from the primary application service provider. By default, we recommend
// using the other overload, which allows Entity Framework to create and maintain
// its own System.IServiceProvider for internal Entity Framework services.
//
// Parameters:
// serviceCollection:
// The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
// to.
//
// optionsAction:
// An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
// for the context. This provides an alternative to performing configuration of
// the context by overriding the Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
//
// method in your derived context.
// If an action is supplied here, the
// Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
// method will still be run if it has been overridden on the
// derived context. Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
// configuration will be applied in addition to configuration performed here.
// In order for the options to be passed into your context, you need
// to expose a constructor on your context that takes
// Microsoft.EntityFrameworkCore.DbContextOptions`1
// and passes it to the base constructor of
// Microsoft.EntityFrameworkCore.DbContext.
//
// contextLifetime:
// The lifetime with which to register the DbContext
// service in the container.
//
// optionsLifetime:
// The lifetime with which to register the DbContextOptions
// service in the container.
//
// Type parameters:
// TContext:
// The type of context to be registered.
//
// Returns:
// The same service collection so that multiple calls can be chained.
public static IServiceCollection AddDbContext<TContext>(
[NotNullAttribute] this IServiceCollection serviceCollection,
[CanBeNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction,
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped
) where TContext : DbContext;
我正在尝试 .net 核心 Web api。我创建了一个静态方法来像这样注册我的控制器:
public static class RegistrationExtensions
{
public static void RegisterApplicationServices(this IServiceCollection services, IServiceProvider serviceProvider)
{
services.RegisterSingletons();
services.RegisterRequests();
services.RegisterTransient(serviceProvider);
}
public static void RegisterSingletons(this IServiceCollection services)
{
services.AddSingleton<Configuration>();
}
public static void RegisterRequests(this IServiceCollection services)
{
services.AddScoped<ISettingsService, SettingsService>();
}
public static void RegisterTransient(this IServiceCollection services, IServiceProvider serviceProvider)
{
var config = serviceProvider.GetService<Configuration>();
services.AddDbContext<InteractiveChoicesContext>(m => m.UseSqlServer(config.ConnectionString));
}
}
如您所见,我想解析我的 Configuration class,其中包含我传入的 ConnectionString DbContext。 请解决 Configuration 我试图使用 IServiceProvider 注入到 RegisterApplicationServices 方法中。
为了调用此方法,我将 Startup class 的 ConfigureServices 更改为:
public void ConfigureServices(IServiceCollection services, IServiceProvider serviceProvider)
{
services.AddMvc();
services.RegisterApplicationServices(serviceProvider);
}
但是当我 运行 我的应用程序时,我得到一个错误:
The ConfigureServices method must either be parameterless or take only one parameter of type IServiceCollection.
错误很明显。我的问题是:如何在我的 RegisterTransient 方法中解决 Configuration class?
如果您必须使用您自己的配置 class 而不是使用 IConfiguration
,您可以这样做来解决您目前配置的 IServiceCollection
,在您的情况下已经有注册您的 Configuration
单身人士:
public static void RegisterTransient(this IServiceCollection services)
{
// Use services registered so far
var serviceProvider = services.BuildServiceProvider();
var config = serviceProvider.GetRequiredService<Configuration>();
services.AddDbContext<InteractiveChoicesContext>(m => m.UseSqlServer(config.ConnectionString));
}
其中 BuildServiceProvider()
是程序集 Microsoft.Extensions.DependencyInjection
、命名空间 Microsoft.Extensions.DependencyInjection
中的扩展方法。
实际上有一个 AddDbContext
的重载,它需要一个 Action<IServiceProvider, DbContextOptionsBuilder>
,这应该正是您要查找的内容。
例如:
services.AddDbContext<InteractiveChoicesContext>((provider, options) =>
{
var config = provider.GetService<Configuration>();
options.UseSqlServer(config.ConnectionString);
});
我已经用 v2、v3 和 v5 对此进行了测试。 EF Core 2.0.0 中指定的此重载的文档被逐字包含以供后代和相关性使用
//
// Summary:
// Registers the given context as a service in the
// Microsoft.Extensions.DependencyInjection.IServiceCollection.
// You use this method when using dependency injection in your application, such
// as with ASP.NET. For more information on setting up dependency injection, see
// http://go.microsoft.com/fwlink/?LinkId=526890.
// This overload has an optionsAction that provides the applications
// System.IServiceProvider.
// This is useful if you want to setup Entity Framework to resolve its internal
// services from the primary application service provider. By default, we recommend
// using the other overload, which allows Entity Framework to create and maintain
// its own System.IServiceProvider for internal Entity Framework services.
//
// Parameters:
// serviceCollection:
// The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services
// to.
//
// optionsAction:
// An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions
// for the context. This provides an alternative to performing configuration of
// the context by overriding the Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
//
// method in your derived context.
// If an action is supplied here, the
// Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
// method will still be run if it has been overridden on the
// derived context. Microsoft.EntityFrameworkCore.DbContext
// .OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)
// configuration will be applied in addition to configuration performed here.
// In order for the options to be passed into your context, you need
// to expose a constructor on your context that takes
// Microsoft.EntityFrameworkCore.DbContextOptions`1
// and passes it to the base constructor of
// Microsoft.EntityFrameworkCore.DbContext.
//
// contextLifetime:
// The lifetime with which to register the DbContext
// service in the container.
//
// optionsLifetime:
// The lifetime with which to register the DbContextOptions
// service in the container.
//
// Type parameters:
// TContext:
// The type of context to be registered.
//
// Returns:
// The same service collection so that multiple calls can be chained.
public static IServiceCollection AddDbContext<TContext>(
[NotNullAttribute] this IServiceCollection serviceCollection,
[CanBeNullAttribute] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction,
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped
) where TContext : DbContext;