在Aspnet Core 的啟動配置中,StartUp 類中,有配置數據庫 DI服務的部分:
按個人看源代碼的理解,下列方法實際是在DI 注冊了兩個類:
一個是:ApplicationDbContext,另一個是: DbContextOptions,及 DbContextOptions<ApplicationDbContext>,
實際主要涉及三個類:DbContext,DbContextOptionsBuilder,及 DbContextOptions (通過 DbContextOptionsBuilder.Options 獲得,沒有 Build 方法)
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddDbContext<ApplicationDbContext>(Action<DbContextOptionsBuilder> optionsAction);
services.AddDbContext<ApplicationDbContext>(Action<IServiceProvider, DbContextOptionsBuilder> optionsAction);
//其它相關服務:DbContextOptionsBuilder 的方法與 屬性 Options = DbContextOptions
UseSqlServer(DbContextOptionsBuilder, String, Action<SqlServerDbContextOptionsBuilder>);
} }
AddDBContext 的 Github源代碼,有幾個,最后調用 最全參數的那個,efcore/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs, 參考 :
public static IServiceCollection AddDbContext<TContextService, TContextImplementation> (
[NotNull] this IServiceCollection serviceCollection,
[CanBeNull] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction,
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped ) where TContextImplementation : DbContext, TContextService
{
Check.NotNull(serviceCollection, nameof(serviceCollection)); // 這個方法在哪里定義???
if (contextLifetime == ServiceLifetime.Singleton)
{
optionsLifetime = ServiceLifetime.Singleton;
}
if (optionsAction != null)
{
CheckContextConstructors<TContextImplementation>(); // 檢查TContextImplementation類的構造器是可有參數。
}
AddCoreServices<TContextImplementation>(serviceCollection, optionsAction, optionsLifetime);
// TryAdd 方法定義:Add(IServiceCollection, ServiceDescriptor) 其中 ServiceDescriptor 的定義。
// 使用 構造函數 ServiceDescriptor(Type, Type, ServiceLifetime)
serviceCollection.TryAdd(new ServiceDescriptor(typeof(TContextService), typeof(TContextImplementation), contextLifetime));
return serviceCollection;
}
private static void AddCoreServices<TContextImplementation> (
IServiceCollection serviceCollection,
Action<IServiceProvider, DbContextOptionsBuilder> optionsAction,
ServiceLifetime optionsLifetime ) where TContextImplementation : DbContext
{
// TryAdd 方法定義:Add(IServiceCollection, ServiceDescriptor)
// 使用 構造函數 ServiceDescriptor(Type, Func<IServiceProvider,Object>, ServiceLifetime)
serviceCollection.TryAdd( new ServiceDescriptor( typeof(DbContextOptions<TContextImplementation>),
p => CreateDbContextOptions<TContextImplementation>(p, optionsAction), optionsLifetime));
serviceCollection.Add( new ServiceDescriptor( typeof(DbContextOptions),
p => p.GetRequiredService<DbContextOptions<TContextImplementation>>(), optionsLifetime));
}
private static DbContextOptions<TContext> CreateDbContextOptions<TContext>(
[NotNull] IServiceProvider applicationServiceProvider,
[CanBeNull] Action<IServiceProvider, DbContextOptionsBuilder> optionsAction) where TContext : DbContext
{
var builder = new DbContextOptionsBuilder<TContext>(
new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>()));
builder.UseApplicationServiceProvider(applicationServiceProvider);
optionsAction?.Invoke(applicationServiceProvider, builder);
return builder.Options;
}