在 asp.net core 2.1 MVC 应用程序中,我有以下代码,部分来自 Github 上的一个 block ,以及我所做的一些添加:
public static IServiceCollection AddIdentityMongoDbProvider<TUser, TRole>(this IServiceCollection services, Action<IdentityOptions> setupIdentityAction, Action<MongoIdentityOptions> setupDatabaseAction) where TUser : UserEntity where TRole : RoleEntity
{
services.AddIdentity<TUser, TRole>(setupIdentityAction ?? (x => { }))
.AddRoleStore<RoleStore<TRole>>()
.AddUserStore<UserStore<TUser, TRole>>()
.AddDefaultTokenProviders();
var dbOptions = new MongoIdentityOptions();
setupDatabaseAction(dbOptions);
var userCollection = new IdentityUserCollection<TUser>(dbOptions.DbType, dbOptions.ConnectionString);
var roleCollection = new IdentityRoleCollection<TRole>(dbOptions.DbType, dbOptions.ConnectionString);
// Add collections and stores in services for DI
services.AddTransient<IIdentityUserCollection<TUser>>(x => userCollection);
services.AddTransient<IIdentityRoleCollection<TRole>>(x => roleCollection);
services.AddTransient<ITenantStore<TenantEntity, TUser>>(x => new TenantStore<TenantEntity, TUser>(dbOptions.DbType, dbOptions.ConnectionString, userCollection));
services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));
// Identity Services
services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));
services.AddTransient<IRoleStore<TRole>>(x => new RoleStore<TRole>(roleCollection));
return services;
}
正如您所看到的,它使用依赖注入(inject),但我问自己一些问题:
1) userCollection 和 roleCollection 是“本地”变量,然后传递到 DI 中。那么这些对象的生命周期是如何管理的呢?我的意思是它们从未被丢弃,因为它们被用于 DI 中?或者他们每次都在创造?
2)有什么区别
services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));
还有
services.AddTransient<ILicenseStore<LicenseEntity>>(new LicenseStore<LicenseEntity>(dbOptions.DbType, dbOptions.ConnectionString));
3)在行中
services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));
有“x.GetService()”。这是一种告诉构造函数构造函数中所需的参数将来自 DI 的方法吗?有点像在 DependecyInjection 中使用依赖注入(inject)?
4)如果问题3为"is",是否可以做这样的事情?
services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));
services.AddTransient<IXStore>(new XStore(x.GetService<IMongoClient>()))
重点是要实现 MongoClient 将是单例(这是推荐的方式)
5)两者之间有什么区别:
services.AddScoped((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(x.GetRequiredService<IIdentityUserCollection<TUser>>(), x.GetRequiredService<IIdentityRoleCollection<TRole>>(), x.GetService<ILookupNormalizer>())));
还有
services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole>>();
非常感谢您的回答:)
编辑:
新方法:
services.AddSingleton<ICustomMongoClient>(x => new CustomMongoClient(dbOptions.ConnectionString));
// Add collections and stores in services for DI
services.AddTransient<IIdentityUserCollection<TUser>>(x => new IdentityUserCollection<TUser>(x.GetRequiredService<ICustomMongoClient>()));
services.AddTransient<IIdentityRoleCollection<TRole>>(x => new IdentityRoleCollection<TRole>(x.GetRequiredService<ICustomMongoClient>()));
services.AddTransient<ITenantStore<TenantEntity, TUser>>(x => new TenantStore<TenantEntity, TUser>(x.GetRequiredService<ICustomMongoClient>(), x.GetRequiredService<IIdentityUserCollection<TUser>>()));
services.AddTransient<ILicenseStore<LicenseEntity>>(x => new LicenseStore<LicenseEntity>(x.GetRequiredService<ICustomMongoClient>()));
// Identity Services
services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(x.GetRequiredService<IIdentityUserCollection<TUser>>(), x.GetRequiredService<IIdentityRoleCollection<TRole>>(), x.GetService<ILookupNormalizer>())));
services.AddTransient<IRoleStore<TRole>>(x => new RoleStore<TRole>(x.GetRequiredService<IIdentityRoleCollection<TRole>>()));
最佳答案
首先
userCollection
和roleCollection
仅实例化一次。由于以下原因,这两个局部变量都不会被垃圾收集。它们由使用 lambda(x => userCollection
和x => roleCollection
)创建的委托(delegate)捕获,并且委托(delegate)被添加到服务集合中,这绝对是 GC root 。 .是的,有。第一行可以编译,后一行则不能。您只能将构造对象传递给
AddSingleton
。services.AddSingleton(x => new object)
之间唯一的区别和services.AddSingleton(new object)
是在实例化对象时,立即 (new object
) 或在第一次请求指定服务类型时 (x => new object
)。是的。
如果修复第二行
services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));
services.AddTransient<IXStore>(x => new XStore(x.GetService<IMongoClient>()))
那么答案是是。事实上DI容器会为你做这件事,调用GetService
对于每个构造函数参数。所以下面的代码相当于你的
services.AddSingletion<IMongoClient>(new MongoClient("connectionString"));
services.AddTransient<IXStore, XStore>()
基本上这两个示例是相同的。当您使用第一个示例时,您可以使用
DI
手动解析所有构造函数参数。容器。当您使用第二个时DI
容器会自动为您解析所有构造函数参数。因此在这种情况下更喜欢第二种方法,因为它的代码更少。仅当您需要使用new
自己实例化对象时才考虑使用第一种方法或为他们提供一些其他服务而不是DI
容器。
关于asp.net-core - asp.net core 2.1 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54929014/